From c12a1c6898c5db300bfeceea50438b328601705d Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 14:48:34 -0300 Subject: [PATCH 001/205] fix linter error --- test/token/ERC20/behaviors/ERC20Capped.behavior.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/token/ERC20/behaviors/ERC20Capped.behavior.js b/test/token/ERC20/behaviors/ERC20Capped.behavior.js index a22a99632..3c3ab7fbf 100644 --- a/test/token/ERC20/behaviors/ERC20Capped.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Capped.behavior.js @@ -1,5 +1,4 @@ const { expectThrow } = require('../../../helpers/expectThrow'); -const expectEvent = require('../../../helpers/expectEvent'); const BigNumber = web3.BigNumber; From 13b19612d6e2a09f9b898cc9144ed7fa89a33bd9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 15:22:16 -0300 Subject: [PATCH 002/205] add note about trying out 2.0 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a912ac734..54e6f79e0 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ npm install openzeppelin-solidity ``` +If you're interested in trying out a preview of OpenZeppelin 2.0, install `openzeppelin-solidity@next`, check out the [release notes](https://github.com/OpenZeppelin/openzeppelin-solidity/releases/tag/v2.0.0-rc.1), and let us know what you think! + ## Usage To write your custom contracts, import ours and extend them through inheritance. From 651f6d8b57f5b67cda69656c70b8db4136f7d72f Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 15:41:43 -0300 Subject: [PATCH 003/205] fix readme snippet so it is concrete --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 54e6f79e0..24dfaa681 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,14 @@ If you're interested in trying out a preview of OpenZeppelin 2.0, install `openz To write your custom contracts, import ours and extend them through inheritance. ```solidity -import 'openzeppelin-solidity/contracts/token/ERC721/ERC721.sol'; +pragma solidity ^0.4.24; + +import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol'; import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol'; -contract MyNFT is ERC721, ERC721Mintable { +contract MyNFT is ERC721Full, ERC721Mintable { + constructors() ERC721Full("MyNFT", "MNFT") public { + } } ``` From 0b8296e52596db8ef97f313fe3507cac8fbbcde3 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 15:45:29 -0300 Subject: [PATCH 004/205] Fix README snippet typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24dfaa681..0b309d7c8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol'; import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol'; contract MyNFT is ERC721Full, ERC721Mintable { - constructors() ERC721Full("MyNFT", "MNFT") public { + constructor() ERC721Full("MyNFT", "MNFT") public { } } ``` From b644c72eb083d7a84a5c9924ec8012a7c29290fd Mon Sep 17 00:00:00 2001 From: Jerome de Tychey Date: Mon, 10 Sep 2018 17:06:52 +0200 Subject: [PATCH 005/205] Update ERC20.sol (#1313) correct typo in doc --- contracts/token/ERC20/ERC20.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index d1f3094d4..34cb3f6ce 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -29,7 +29,7 @@ contract ERC20 is IERC20 { /** * @dev Gets the balance of the specified address. - * @param owner The address to query the the balance of. + * @param owner The address to query the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { From d8cbd5554f4565b9bd535469bc87c75cdc25b3c5 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Tue, 11 Sep 2018 21:51:11 +0700 Subject: [PATCH 006/205] update Math.sol path (#1319) --- contracts/mocks/MathMock.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index 60341bc65..696653858 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "../../contracts/math/Math.sol"; +import "../math/Math.sol"; contract MathMock { From b79196f911d013e1d3930e395cc5646917992cc3 Mon Sep 17 00:00:00 2001 From: dwardu Date: Tue, 11 Sep 2018 17:32:05 +0200 Subject: [PATCH 007/205] Fixed a broken payment test (+ another small fix) (#1318) * Fixed a broken payment test * In PR template, npm run lint:fix, not lint:all:fix * In SplitPayment test, replaced an await-in-loop with Promise.all --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- test/payment/SplitPayment.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c32ba08f2..72b331668 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,4 +14,4 @@ Fixes # - [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md) - [ ] ✅ I've added tests where applicable to test my new functionality. - [ ] 📖 I've made sure that my contracts are well-documented. -- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:all:fix`). +- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:fix`). diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index 788296016..05cc0b701 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -51,10 +51,10 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should have payees', async function () { - this.payees.forEach(async (payee, index) => { - (await this.payee(index)).should.be.equal(payee); + await Promise.all(this.payees.map(async (payee, index) => { + (await this.contract.payee(index)).should.be.equal(payee); (await this.contract.released(payee)).should.be.bignumber.equal(0); - }); + })); }); it('should accept payments', async function () { From 7825caa1fdf8bec80ad43f4da15cf5ee4c9a8e3f Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Wed, 12 Sep 2018 17:49:00 +0200 Subject: [PATCH 008/205] Add unit test specific to Address utils (#1251) (#1316) --- contracts/mocks/AddressImpl.sol | 15 +++++++++++++++ test/Address.test.js | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 contracts/mocks/AddressImpl.sol create mode 100644 test/Address.test.js diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol new file mode 100644 index 000000000..b46fd06c3 --- /dev/null +++ b/contracts/mocks/AddressImpl.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.24; + +import "../utils/Address.sol"; + + +contract AddressImpl { + function isContract(address account) + external + view + returns (bool) + { + return Address.isContract(account); + } + +} diff --git a/test/Address.test.js b/test/Address.test.js new file mode 100644 index 000000000..f41e57565 --- /dev/null +++ b/test/Address.test.js @@ -0,0 +1,20 @@ +const AddressImpl = artifacts.require('AddressImpl'); +const SimpleToken = artifacts.require('SimpleToken'); + +require('chai') + .should(); + +contract('Address', function ([_, anyone]) { + beforeEach(async function () { + this.mock = await AddressImpl.new(); + }); + + it('should return false for account address', async function () { + (await this.mock.isContract(anyone)).should.equal(false); + }); + + it('should return true for contract address', async function () { + const contract = await SimpleToken.new(); + (await this.mock.isContract(contract.address)).should.equal(true); + }); +}); From 225b492109ca83eda6f3af62265226c13ef2ba5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 12 Sep 2018 16:17:47 -0300 Subject: [PATCH 009/205] Fixed relative imports. (#1321) --- contracts/mocks/InsecureInvariantTargetBounty.sol | 2 +- contracts/mocks/SecureInvariantTargetBounty.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/mocks/InsecureInvariantTargetBounty.sol b/contracts/mocks/InsecureInvariantTargetBounty.sol index 32d305cac..ded818b1a 100644 --- a/contracts/mocks/InsecureInvariantTargetBounty.sol +++ b/contracts/mocks/InsecureInvariantTargetBounty.sol @@ -3,7 +3,7 @@ pragma solidity ^0.4.24; // When this line is split, truffle parsing fails. // See: https://github.com/ethereum/solidity/issues/4871 // solium-disable-next-line max-len -import {BreakInvariantBounty, Target} from "../../contracts/bounties/BreakInvariantBounty.sol"; +import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; contract InsecureInvariantTargetMock is Target { diff --git a/contracts/mocks/SecureInvariantTargetBounty.sol b/contracts/mocks/SecureInvariantTargetBounty.sol index f08fbd9b8..40f2de994 100644 --- a/contracts/mocks/SecureInvariantTargetBounty.sol +++ b/contracts/mocks/SecureInvariantTargetBounty.sol @@ -3,7 +3,7 @@ pragma solidity ^0.4.24; // When this line is split, truffle parsing fails. // See: https://github.com/ethereum/solidity/issues/4871 // solium-disable-next-line max-len -import {BreakInvariantBounty, Target} from "../../contracts/bounties/BreakInvariantBounty.sol"; +import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; contract SecureInvariantTargetMock is Target { From b4f87bb8fc25fb07f73099701e39e167a3d36465 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Thu, 13 Sep 2018 02:51:22 -0600 Subject: [PATCH 010/205] Rename AutoIncrementing to Counter (#1307) --- contracts/mocks/AutoIncrementingImpl.sol | 21 ------------------- contracts/mocks/CounterImpl.sol | 21 +++++++++++++++++++ .../{AutoIncrementing.sol => Counter.sol} | 18 ++++++++-------- ...toIncrementing.test.js => Counter.test.js} | 7 ++++--- 4 files changed, 34 insertions(+), 33 deletions(-) delete mode 100644 contracts/mocks/AutoIncrementingImpl.sol create mode 100644 contracts/mocks/CounterImpl.sol rename contracts/utils/{AutoIncrementing.sol => Counter.sol} (59%) rename test/{AutoIncrementing.test.js => Counter.test.js} (85%) diff --git a/contracts/mocks/AutoIncrementingImpl.sol b/contracts/mocks/AutoIncrementingImpl.sol deleted file mode 100644 index ea15e8e39..000000000 --- a/contracts/mocks/AutoIncrementingImpl.sol +++ /dev/null @@ -1,21 +0,0 @@ -pragma solidity ^0.4.24; - -import "../utils/AutoIncrementing.sol"; - - -contract AutoIncrementingImpl { - using AutoIncrementing for AutoIncrementing.Counter; - - uint256 public theId; - - // use whatever key you want to track your counters - mapping(string => AutoIncrementing.Counter) private _counters; - - function doThing(string key) - public - returns (uint256) - { - theId = _counters[key].nextId(); - return theId; - } -} diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol new file mode 100644 index 000000000..222c0526e --- /dev/null +++ b/contracts/mocks/CounterImpl.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.24; + +import "../utils/Counter.sol"; + + +contract CounterImpl { + using Counter for Counter.Index; + + uint256 public theId; + + // use whatever key you want to track your counters + mapping(string => Counter.Index) private _counters; + + function doThing(string key) + public + returns (uint256) + { + theId = _counters[key].next(); + return theId; + } +} diff --git a/contracts/utils/AutoIncrementing.sol b/contracts/utils/Counter.sol similarity index 59% rename from contracts/utils/AutoIncrementing.sol rename to contracts/utils/Counter.sol index f739e539d..516b798f0 100644 --- a/contracts/utils/AutoIncrementing.sol +++ b/contracts/utils/Counter.sol @@ -2,28 +2,28 @@ pragma solidity ^0.4.24; /** - * @title AutoIncrementing + * @title Counter * @author Matt Condon (@shrugs) - * @dev Provides an auto-incrementing uint256 id acquired by the `Counter#nextId` getter. + * @dev Provides an incrementing uint256 id acquired by the `Index#next` getter. * Use this for issuing ERC721 ids or keeping track of request ids, anything you want, really. * - * Include with `using AutoIncrementing for AutoIncrementing.Counter;` + * Include with `using Counter for Counter.Index;` * @notice Does not allow an Id of 0, which is popularly used to signify a null state in solidity. * Does not protect from overflows, but if you have 2^256 ids, you have other problems. * (But actually, it's generally impossible to increment a counter this many times, energy wise * so it's not something you have to worry about.) */ -library AutoIncrementing { +library Counter { - struct Counter { - uint256 prevId; // default: 0 + struct Index { + uint256 currentId; // default: 0 } - function nextId(Counter storage counter) + function next(Index storage index) internal returns (uint256) { - counter.prevId = counter.prevId + 1; - return counter.prevId; + index.currentId = index.currentId + 1; + return index.currentId; } } diff --git a/test/AutoIncrementing.test.js b/test/Counter.test.js similarity index 85% rename from test/AutoIncrementing.test.js rename to test/Counter.test.js index 6b4815830..ca661c113 100644 --- a/test/AutoIncrementing.test.js +++ b/test/Counter.test.js @@ -1,4 +1,5 @@ -const AutoIncrementing = artifacts.require('AutoIncrementingImpl'); + +const Counter = artifacts.require('CounterImpl'); require('chai') .use(require('chai-bignumber')(web3.BigNumber)) @@ -8,9 +9,9 @@ const EXPECTED = [1, 2, 3, 4]; const KEY1 = web3.sha3('key1'); const KEY2 = web3.sha3('key2'); -contract('AutoIncrementing', function ([_, owner]) { +contract('Counter', function ([_, owner]) { beforeEach(async function () { - this.mock = await AutoIncrementing.new({ from: owner }); + this.mock = await Counter.new({ from: owner }); }); context('custom key', async function () { From d062352de78b02435e793ed13991dfdf210f8a29 Mon Sep 17 00:00:00 2001 From: Roman Exempliarov Date: Mon, 17 Sep 2018 23:21:01 +0300 Subject: [PATCH 011/205] Remove lodash from tests (#1323) --- test/helpers/sendTransaction.js | 3 +-- test/token/ERC721/ERC721.behavior.js | 5 +++-- test/token/ERC721/ERC721Full.test.js | 16 ++++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/test/helpers/sendTransaction.js b/test/helpers/sendTransaction.js index 741063209..e49376b44 100644 --- a/test/helpers/sendTransaction.js +++ b/test/helpers/sendTransaction.js @@ -1,9 +1,8 @@ -const _ = require('lodash'); const ethjsABI = require('ethjs-abi'); function findMethod (abi, name, args) { for (let i = 0; i < abi.length; i++) { - const methodArgs = _.map(abi[i].inputs, 'type').join(','); + const methodArgs = abi[i].inputs.map(input => input.type).join(','); if ((abi[i].name === name) && (methodArgs === args)) { return abi[i]; } diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index 03e83fabe..51e2d1015 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -2,7 +2,6 @@ const { shouldSupportInterfaces } = require('../../introspection/SupportsInterfa const { assertRevert } = require('../../helpers/assertRevert'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); -const _ = require('lodash'); const ERC721Receiver = artifacts.require('ERC721ReceiverMock.sol'); const BigNumber = web3.BigNumber; @@ -175,7 +174,9 @@ function shouldBehaveLikeERC721 ( it('keeps same tokens by index', async function () { if (!this.token.tokenOfOwnerByIndex) return; - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(owner, i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenOfOwnerByIndex(owner, i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); }); diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index ce8e915fa..f4666d0d9 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -2,7 +2,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldBehaveLikeMintAndBurnERC721 } = require('./ERC721MintBurn.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); -const _ = require('lodash'); const BigNumber = web3.BigNumber; const ERC721FullMock = artifacts.require('ERC721FullMock.sol'); @@ -173,7 +172,9 @@ contract('ERC721Full', function ([ it('returns correct token IDs for target', async function () { (await this.token.balanceOf(another)).toNumber().should.be.equal(2); - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(another, i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenOfOwnerByIndex(another, i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); @@ -186,7 +187,9 @@ contract('ERC721Full', function ([ describe('tokenByIndex', function () { it('should return all tokens', async function () { - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenByIndex(i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenByIndex(i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); @@ -205,9 +208,10 @@ contract('ERC721Full', function ([ (await this.token.totalSupply()).toNumber().should.be.equal(3); - const tokensListed = await Promise.all(_.range(3).map(i => this.token.tokenByIndex(i))); - const expectedTokens = _.filter( - [firstTokenId, secondTokenId, newTokenId, anotherNewTokenId], + const tokensListed = await Promise.all( + [0, 1, 2].map(i => this.token.tokenByIndex(i)) + ); + const expectedTokens = [firstTokenId, secondTokenId, newTokenId, anotherNewTokenId].filter( x => (x !== tokenId) ); tokensListed.map(t => t.toNumber()).should.have.members(expectedTokens); From 4b21fcf5af6b411d6c39b0616e25d91c811d0768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn?= Date: Tue, 18 Sep 2018 16:24:51 -0300 Subject: [PATCH 012/205] Add Mock suffix to variable names #1172 (#1324) * Add Mock suffix to variable names #1172 * Add Impl suffix to variable names --- test/Counter.test.js | 4 ++-- test/crowdsale/AllowanceCrowdsale.test.js | 6 +++--- test/crowdsale/CappedCrowdsale.test.js | 6 +++--- test/crowdsale/FinalizableCrowdsale.test.js | 4 ++-- test/crowdsale/IncreasingPriceCrowdsale.test.js | 8 ++++---- test/crowdsale/MintedCrowdsale.test.js | 6 +++--- test/crowdsale/PostDeliveryCrowdsale.test.js | 4 ++-- test/crowdsale/RefundableCrowdsale.test.js | 6 +++--- test/crowdsale/TimedCrowdsale.test.js | 10 ++++++---- test/drafts/ERC1046/TokenMetadata.test.js | 4 ++-- test/introspection/ERC165.test.js | 4 ++-- test/token/ERC20/ERC20.test.js | 4 ++-- test/token/ERC20/ERC20Pausable.test.js | 4 ++-- test/token/ERC721/ERC721.behavior.js | 12 ++++++------ test/token/ERC721/ERC721.test.js | 4 ++-- test/token/ERC721/ERC721Burnable.test.js | 4 ++-- test/token/ERC721/ERC721Mintable.test.js | 4 ++-- test/token/ERC721/ERC721Pausable.test.js | 4 ++-- 18 files changed, 50 insertions(+), 48 deletions(-) diff --git a/test/Counter.test.js b/test/Counter.test.js index ca661c113..8a2929d93 100644 --- a/test/Counter.test.js +++ b/test/Counter.test.js @@ -1,5 +1,5 @@ -const Counter = artifacts.require('CounterImpl'); +const CounterImpl = artifacts.require('CounterImpl'); require('chai') .use(require('chai-bignumber')(web3.BigNumber)) @@ -11,7 +11,7 @@ const KEY2 = web3.sha3('key2'); contract('Counter', function ([_, owner]) { beforeEach(async function () { - this.mock = await Counter.new({ from: owner }); + this.mock = await CounterImpl.new({ from: owner }); }); context('custom key', async function () { diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index ee6a063f2..c35707d6d 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -8,7 +8,7 @@ const should = require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const AllowanceCrowdsale = artifacts.require('AllowanceCrowdsaleImpl'); +const AllowanceCrowdsaleImpl = artifacts.require('AllowanceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenWallet]) { @@ -20,7 +20,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW beforeEach(async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - this.crowdsale = await AllowanceCrowdsale.new(rate, wallet, this.token.address, tokenWallet); + this.crowdsale = await AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, tokenWallet); await this.token.approve(this.crowdsale.address, tokenAllowance, { from: tokenWallet }); }); @@ -73,7 +73,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('when token wallet is different from token address', function () { it('creation reverts', async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - await assertRevert(AllowanceCrowdsale.new(rate, wallet, this.token.address, ZERO_ADDRESS)); + await assertRevert(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); }); }); }); diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index 94ed0aedd..5ccfafba3 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -8,7 +8,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const CappedCrowdsale = artifacts.require('CappedCrowdsaleImpl'); +const CappedCrowdsaleImpl = artifacts.require('CappedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('CappedCrowdsale', function ([_, wallet]) { @@ -23,14 +23,14 @@ contract('CappedCrowdsale', function ([_, wallet]) { it('rejects a cap of zero', async function () { await expectThrow( - CappedCrowdsale.new(rate, wallet, this.token.address, 0), + CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0), EVMRevert, ); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await CappedCrowdsale.new(rate, wallet, this.token.address, cap); + this.crowdsale = await CappedCrowdsaleImpl.new(rate, wallet, this.token.address, cap); await this.token.transfer(this.crowdsale.address, tokenSupply); }); diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index df7a743dd..187c67a36 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -10,7 +10,7 @@ const should = require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const FinalizableCrowdsale = artifacts.require('FinalizableCrowdsaleImpl'); +const FinalizableCrowdsaleImpl = artifacts.require('FinalizableCrowdsaleImpl'); const ERC20 = artifacts.require('ERC20'); contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { @@ -27,7 +27,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { this.afterClosingTime = this.closingTime + duration.seconds(1); this.token = await ERC20.new(); - this.crowdsale = await FinalizableCrowdsale.new( + this.crowdsale = await FinalizableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address ); }); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index c62c17d89..767b5f8e5 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -10,7 +10,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const IncreasingPriceCrowdsale = artifacts.require('IncreasingPriceCrowdsaleImpl'); +const IncreasingPriceCrowdsaleImpl = artifacts.require('IncreasingPriceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -36,20 +36,20 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('rejects a final rate larger than the initial rate', async function () { - await assertRevert(IncreasingPriceCrowdsale.new( + await assertRevert(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); it('rejects a final rate of zero', async function () { - await assertRevert(IncreasingPriceCrowdsale.new( + await assertRevert(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await IncreasingPriceCrowdsale.new( + this.crowdsale = await IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, finalRate ); await this.token.transfer(this.crowdsale.address, tokenSupply); diff --git a/test/crowdsale/MintedCrowdsale.test.js b/test/crowdsale/MintedCrowdsale.test.js index e254ddf1b..a3c846b2d 100644 --- a/test/crowdsale/MintedCrowdsale.test.js +++ b/test/crowdsale/MintedCrowdsale.test.js @@ -4,7 +4,7 @@ const { assertRevert } = require('../helpers/assertRevert'); const BigNumber = web3.BigNumber; -const MintedCrowdsale = artifacts.require('MintedCrowdsaleImpl'); +const MintedCrowdsaleImpl = artifacts.require('MintedCrowdsaleImpl'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20 = artifacts.require('ERC20'); @@ -15,7 +15,7 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] describe('using ERC20Mintable', function () { beforeEach(async function () { this.token = await ERC20Mintable.new({ from: deployer }); - this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address); + this.crowdsale = await MintedCrowdsaleImpl.new(rate, wallet, this.token.address); await this.token.addMinter(this.crowdsale.address, { from: deployer }); await this.token.renounceMinter({ from: deployer }); @@ -31,7 +31,7 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] describe('using non-mintable token', function () { beforeEach(async function () { this.token = await ERC20.new(); - this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address); + this.crowdsale = await MintedCrowdsaleImpl.new(rate, wallet, this.token.address); }); it('rejects bare payments', async function () { diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index e95c5a1f4..94ebd808b 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -11,7 +11,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const PostDeliveryCrowdsale = artifacts.require('PostDeliveryCrowdsaleImpl'); +const PostDeliveryCrowdsaleImpl = artifacts.require('PostDeliveryCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -28,7 +28,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { this.closingTime = this.openingTime + duration.weeks(1); this.afterClosingTime = this.closingTime + duration.seconds(1); this.token = await SimpleToken.new(); - this.crowdsale = await PostDeliveryCrowdsale.new( + this.crowdsale = await PostDeliveryCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address ); await this.token.transfer(this.crowdsale.address, tokenSupply); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 3a5305ceb..749ec5cac 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -12,7 +12,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const RefundableCrowdsale = artifacts.require('RefundableCrowdsaleImpl'); +const RefundableCrowdsaleImpl = artifacts.require('RefundableCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyone]) { @@ -37,7 +37,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon it('rejects a goal of zero', async function () { await expectThrow( - RefundableCrowdsale.new( + RefundableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address, 0, ), EVMRevert, @@ -46,7 +46,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await RefundableCrowdsale.new( + this.crowdsale = await RefundableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address, goal ); diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index 4c7eff303..df3e01c81 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -11,7 +11,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const TimedCrowdsale = artifacts.require('TimedCrowdsaleImpl'); +const TimedCrowdsaleImpl = artifacts.require('TimedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -32,20 +32,22 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('rejects an opening time in the past', async function () { - await expectThrow(TimedCrowdsale.new( + await expectThrow(TimedCrowdsaleImpl.new( (await latestTime()) - duration.days(1), this.closingTime, rate, wallet, this.token.address ), EVMRevert); }); it('rejects a closing time before the opening time', async function () { - await expectThrow(TimedCrowdsale.new( + await expectThrow(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - duration.seconds(1), rate, wallet, this.token.address ), EVMRevert); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await TimedCrowdsale.new(this.openingTime, this.closingTime, rate, wallet, this.token.address); + this.crowdsale = await TimedCrowdsaleImpl.new( + this.openingTime, this.closingTime, rate, wallet, this.token.address + ); await this.token.transfer(this.crowdsale.address, tokenSupply); }); diff --git a/test/drafts/ERC1046/TokenMetadata.test.js b/test/drafts/ERC1046/TokenMetadata.test.js index ef0a2ca3d..9810d9119 100644 --- a/test/drafts/ERC1046/TokenMetadata.test.js +++ b/test/drafts/ERC1046/TokenMetadata.test.js @@ -1,4 +1,4 @@ -const ERC20WithMetadata = artifacts.require('ERC20WithMetadataMock'); +const ERC20WithMetadataMock = artifacts.require('ERC20WithMetadataMock'); require('chai') .should(); @@ -7,7 +7,7 @@ const metadataURI = 'https://example.com'; describe('ERC20WithMetadata', function () { beforeEach(async function () { - this.token = await ERC20WithMetadata.new(metadataURI); + this.token = await ERC20WithMetadataMock.new(metadataURI); }); it('responds with the metadata', async function () { diff --git a/test/introspection/ERC165.test.js b/test/introspection/ERC165.test.js index 37a24637d..dc04edaa2 100644 --- a/test/introspection/ERC165.test.js +++ b/test/introspection/ERC165.test.js @@ -1,14 +1,14 @@ const { shouldSupportInterfaces } = require('./SupportsInterface.behavior'); const { assertRevert } = require('../helpers/assertRevert'); -const ERC165 = artifacts.require('ERC165Mock'); +const ERC165Mock = artifacts.require('ERC165Mock'); require('chai') .should(); contract('ERC165', function () { beforeEach(async function () { - this.mock = await ERC165.new(); + this.mock = await ERC165Mock.new(); }); it('does not allow 0xffffffff', async function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index f9568b87e..3662a41a7 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -1,7 +1,7 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); -const ERC20 = artifacts.require('ERC20Mock'); +const ERC20Mock = artifacts.require('ERC20Mock'); const BigNumber = web3.BigNumber; @@ -13,7 +13,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { - this.token = await ERC20.new(owner, 100); + this.token = await ERC20Mock.new(owner, 100); }); describe('total supply', function () { diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index 568b7f147..fa733a3f6 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,11 +1,11 @@ const { assertRevert } = require('../../helpers/assertRevert'); -const ERC20Pausable = artifacts.require('ERC20PausableMock'); +const ERC20PausableMock = artifacts.require('ERC20PausableMock'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherAccount, ...otherAccounts]) { beforeEach(async function () { - this.token = await ERC20Pausable.new(pauser, 100, { from: pauser }); + this.token = await ERC20PausableMock.new(pauser, 100, { from: pauser }); }); describe('pauser role', function () { diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index 51e2d1015..ecdc3352f 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -3,7 +3,7 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); -const ERC721Receiver = artifacts.require('ERC721ReceiverMock.sol'); +const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol'); const BigNumber = web3.BigNumber; require('chai') @@ -237,7 +237,7 @@ function shouldBehaveLikeERC721 ( describe('to a valid receiver contract', function () { beforeEach(async function () { - this.receiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, false); + this.receiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, false); this.toWhom = this.receiver.address; }); @@ -246,7 +246,7 @@ function shouldBehaveLikeERC721 ( it('should call onERC721Received', async function () { const result = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner }); result.receipt.logs.length.should.be.equal(2); - const [log] = decodeLogs([result.receipt.logs[1]], ERC721Receiver, this.receiver.address); + const [log] = decodeLogs([result.receipt.logs[1]], ERC721ReceiverMock, this.receiver.address); log.event.should.be.equal('Received'); log.args.operator.should.be.equal(owner); log.args.from.should.be.equal(owner); @@ -261,7 +261,7 @@ function shouldBehaveLikeERC721 ( result.receipt.logs.length.should.be.equal(2); const [log] = decodeLogs( [result.receipt.logs[1]], - ERC721Receiver, + ERC721ReceiverMock, this.receiver.address ); log.event.should.be.equal('Received'); @@ -297,14 +297,14 @@ function shouldBehaveLikeERC721 ( describe('to a receiver contract returning unexpected value', function () { it('reverts', async function () { - const invalidReceiver = await ERC721Receiver.new('0x42', false); + const invalidReceiver = await ERC721ReceiverMock.new('0x42', false); await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); }); }); describe('to a receiver contract that throws', function () { it('reverts', async function () { - const invalidReceiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, true); + const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true); await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); }); }); diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index 4c40e3972..eef76eba8 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -1,7 +1,7 @@ const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const BigNumber = web3.BigNumber; -const ERC721 = artifacts.require('ERC721Mock.sol'); +const ERC721Mock = artifacts.require('ERC721Mock.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -9,7 +9,7 @@ require('chai') contract('ERC721', function ([_, creator, ...accounts]) { beforeEach(async function () { - this.token = await ERC721.new({ from: creator }); + this.token = await ERC721Mock.new({ from: creator }); }); shouldBehaveLikeERC721(creator, creator, accounts); diff --git a/test/token/ERC721/ERC721Burnable.test.js b/test/token/ERC721/ERC721Burnable.test.js index a8b011b90..745f7dac2 100644 --- a/test/token/ERC721/ERC721Burnable.test.js +++ b/test/token/ERC721/ERC721Burnable.test.js @@ -4,7 +4,7 @@ const { } = require('./ERC721MintBurn.behavior'); const BigNumber = web3.BigNumber; -const ERC721Burnable = artifacts.require('ERC721MintableBurnableImpl.sol'); +const ERC721BurnableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -14,7 +14,7 @@ contract('ERC721Burnable', function ([_, creator, ...accounts]) { const minter = creator; beforeEach(async function () { - this.token = await ERC721Burnable.new({ from: creator }); + this.token = await ERC721BurnableImpl.new({ from: creator }); }); shouldBehaveLikeERC721(creator, minter, accounts); diff --git a/test/token/ERC721/ERC721Mintable.test.js b/test/token/ERC721/ERC721Mintable.test.js index 65c568643..639c8374d 100644 --- a/test/token/ERC721/ERC721Mintable.test.js +++ b/test/token/ERC721/ERC721Mintable.test.js @@ -4,7 +4,7 @@ const { } = require('./ERC721MintBurn.behavior'); const BigNumber = web3.BigNumber; -const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol'); +const ERC721MintableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -14,7 +14,7 @@ contract('ERC721Mintable', function ([_, creator, ...accounts]) { const minter = creator; beforeEach(async function () { - this.token = await ERC721Mintable.new({ + this.token = await ERC721MintableImpl.new({ from: creator, }); }); diff --git a/test/token/ERC721/ERC721Pausable.test.js b/test/token/ERC721/ERC721Pausable.test.js index 3724655e0..3961368ef 100644 --- a/test/token/ERC721/ERC721Pausable.test.js +++ b/test/token/ERC721/ERC721Pausable.test.js @@ -3,7 +3,7 @@ const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); const BigNumber = web3.BigNumber; -const ERC721Pausable = artifacts.require('ERC721PausableMock.sol'); +const ERC721PausableMock = artifacts.require('ERC721PausableMock.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -18,7 +18,7 @@ contract('ERC721Pausable', function ([ ...accounts ]) { beforeEach(async function () { - this.token = await ERC721Pausable.new({ from: creator }); + this.token = await ERC721PausableMock.new({ from: creator }); }); describe('pauser role', function () { From 3e55408cb5590dc5095ebd766756ca2da356e1d8 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 18 Sep 2018 17:42:31 -0300 Subject: [PATCH 013/205] Changes to Counter (#1332) * rename Index.currentId to current * use += operator for clarity * rename Counter.Index to Counter.Counter * move Counter to drafts --- contracts/{utils => drafts}/Counter.sol | 14 +++++++------- contracts/mocks/CounterImpl.sol | 6 +++--- test/{ => drafts}/Counter.test.js | 0 3 files changed, 10 insertions(+), 10 deletions(-) rename contracts/{utils => drafts}/Counter.sol (66%) rename test/{ => drafts}/Counter.test.js (100%) diff --git a/contracts/utils/Counter.sol b/contracts/drafts/Counter.sol similarity index 66% rename from contracts/utils/Counter.sol rename to contracts/drafts/Counter.sol index 516b798f0..b47d9b824 100644 --- a/contracts/utils/Counter.sol +++ b/contracts/drafts/Counter.sol @@ -4,10 +4,10 @@ pragma solidity ^0.4.24; /** * @title Counter * @author Matt Condon (@shrugs) - * @dev Provides an incrementing uint256 id acquired by the `Index#next` getter. + * @dev Provides an incrementing uint256 id acquired by the `Counter#next` getter. * Use this for issuing ERC721 ids or keeping track of request ids, anything you want, really. * - * Include with `using Counter for Counter.Index;` + * Include with `using Counter for Counter.Counter;` * @notice Does not allow an Id of 0, which is popularly used to signify a null state in solidity. * Does not protect from overflows, but if you have 2^256 ids, you have other problems. * (But actually, it's generally impossible to increment a counter this many times, energy wise @@ -15,15 +15,15 @@ pragma solidity ^0.4.24; */ library Counter { - struct Index { - uint256 currentId; // default: 0 + struct Counter { + uint256 current; // default: 0 } - function next(Index storage index) + function next(Counter storage index) internal returns (uint256) { - index.currentId = index.currentId + 1; - return index.currentId; + index.current += 1; + return index.current; } } diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol index 222c0526e..d42fcbda2 100644 --- a/contracts/mocks/CounterImpl.sol +++ b/contracts/mocks/CounterImpl.sol @@ -1,15 +1,15 @@ pragma solidity ^0.4.24; -import "../utils/Counter.sol"; +import "../drafts/Counter.sol"; contract CounterImpl { - using Counter for Counter.Index; + using Counter for Counter.Counter; uint256 public theId; // use whatever key you want to track your counters - mapping(string => Counter.Index) private _counters; + mapping(string => Counter.Counter) private _counters; function doThing(string key) public diff --git a/test/Counter.test.js b/test/drafts/Counter.test.js similarity index 100% rename from test/Counter.test.js rename to test/drafts/Counter.test.js From 9b3710465583284b8c4c5d2245749246bb2e0094 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 19 Sep 2018 19:59:13 -0300 Subject: [PATCH 014/205] Turn off blank-lines Solium rule (#1284) * turn off blank-lines rule * remove triple newlines --- .soliumrc.json | 1 + contracts/access/Roles.sol | 1 - contracts/access/roles/CapperRole.sol | 1 - contracts/access/roles/MinterRole.sol | 1 - contracts/access/roles/PauserRole.sol | 1 - contracts/access/roles/SignerRole.sol | 1 - contracts/bounties/BreakInvariantBounty.sol | 3 --- contracts/crowdsale/Crowdsale.sol | 1 - contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 1 - contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol | 1 - contracts/crowdsale/distribution/RefundableCrowdsale.sol | 2 -- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 1 - contracts/crowdsale/emission/MintedCrowdsale.sol | 1 - contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 1 - contracts/crowdsale/validation/CappedCrowdsale.sol | 1 - contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol | 1 - contracts/crowdsale/validation/TimedCrowdsale.sol | 1 - contracts/cryptography/ECDSA.sol | 1 - contracts/cryptography/MerkleProof.sol | 1 - contracts/drafts/Counter.sol | 1 - contracts/drafts/ERC1046/TokenMetadata.sol | 2 -- contracts/drafts/ERC20Migrator.sol | 1 - contracts/drafts/SignatureBouncer.sol | 1 - contracts/drafts/TokenVesting.sol | 1 - contracts/examples/SampleCrowdsale.sol | 2 -- contracts/examples/SimpleToken.sol | 2 -- contracts/introspection/ERC165.sol | 1 - contracts/introspection/ERC165Checker.sol | 2 -- contracts/introspection/IERC165.sol | 1 - contracts/lifecycle/Pausable.sol | 2 -- contracts/math/Math.sol | 1 - contracts/math/SafeMath.sol | 1 - contracts/mocks/AddressImpl.sol | 1 - contracts/mocks/AllowanceCrowdsaleImpl.sol | 1 - contracts/mocks/CappedCrowdsaleImpl.sol | 1 - contracts/mocks/CapperRoleMock.sol | 1 - contracts/mocks/ConditionalEscrowMock.sol | 2 -- contracts/mocks/CounterImpl.sol | 1 - contracts/mocks/DetailedERC20Mock.sol | 1 - contracts/mocks/ECDSAMock.sol | 2 -- contracts/mocks/ERC165/ERC165InterfacesSupported.sol | 3 --- contracts/mocks/ERC165/ERC165NotSupported.sol | 1 - contracts/mocks/ERC165CheckerMock.sol | 1 - contracts/mocks/ERC165Mock.sol | 1 - contracts/mocks/ERC20BurnableMock.sol | 1 - contracts/mocks/ERC20MintableMock.sol | 1 - contracts/mocks/ERC20Mock.sol | 1 - contracts/mocks/ERC20PausableMock.sol | 1 - contracts/mocks/ERC20WithMetadataMock.sol | 1 - contracts/mocks/ERC721FullMock.sol | 1 - contracts/mocks/ERC721MintableBurnableImpl.sol | 1 - contracts/mocks/ERC721Mock.sol | 1 - contracts/mocks/ERC721PausableMock.sol | 1 - contracts/mocks/ERC721ReceiverMock.sol | 1 - contracts/mocks/FinalizableCrowdsaleImpl.sol | 1 - contracts/mocks/ForceEther.sol | 1 - contracts/mocks/IncreasingPriceCrowdsaleImpl.sol | 1 - contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol | 1 - contracts/mocks/InsecureInvariantTargetBounty.sol | 2 -- contracts/mocks/MathMock.sol | 2 -- contracts/mocks/MerkleProofWrapper.sol | 1 - contracts/mocks/MessageHelper.sol | 1 - contracts/mocks/MintedCrowdsaleImpl.sol | 1 - contracts/mocks/MinterRoleMock.sol | 1 - contracts/mocks/PausableMock.sol | 2 -- contracts/mocks/PauserRoleMock.sol | 1 - contracts/mocks/PostDeliveryCrowdsaleImpl.sol | 1 - contracts/mocks/PullPaymentMock.sol | 2 -- contracts/mocks/ReentrancyAttack.sol | 1 - contracts/mocks/ReentrancyMock.sol | 1 - contracts/mocks/RefundableCrowdsaleImpl.sol | 1 - contracts/mocks/RolesMock.sol | 1 - contracts/mocks/SafeERC20Helper.sol | 3 --- contracts/mocks/SafeMathMock.sol | 2 -- contracts/mocks/SecondaryMock.sol | 1 - contracts/mocks/SecureInvariantTargetBounty.sol | 2 -- contracts/mocks/SignatureBouncerMock.sol | 1 - contracts/mocks/SignerRoleMock.sol | 1 - contracts/mocks/TimedCrowdsaleImpl.sol | 1 - contracts/ownership/Ownable.sol | 3 --- contracts/ownership/Secondary.sol | 1 - contracts/payment/ConditionalEscrow.sol | 1 - contracts/payment/Escrow.sol | 1 - contracts/payment/PullPayment.sol | 1 - contracts/payment/RefundEscrow.sol | 1 - contracts/payment/SplitPayment.sol | 1 - contracts/token/ERC20/ERC20.sol | 1 - contracts/token/ERC20/ERC20Burnable.sol | 1 - contracts/token/ERC20/ERC20Capped.sol | 1 - contracts/token/ERC20/ERC20Detailed.sol | 1 - contracts/token/ERC20/ERC20Mintable.sol | 1 - contracts/token/ERC20/ERC20Pausable.sol | 1 - contracts/token/ERC20/IERC20.sol | 1 - contracts/token/ERC20/SafeERC20.sol | 1 - contracts/token/ERC20/TokenTimelock.sol | 1 - contracts/token/ERC721/ERC721.sol | 1 - contracts/token/ERC721/ERC721Burnable.sol | 1 - contracts/token/ERC721/ERC721Enumerable.sol | 1 - contracts/token/ERC721/ERC721Full.sol | 1 - contracts/token/ERC721/ERC721Holder.sol | 1 - contracts/token/ERC721/ERC721Metadata.sol | 1 - contracts/token/ERC721/ERC721Mintable.sol | 1 - contracts/token/ERC721/ERC721Pausable.sol | 1 - contracts/token/ERC721/IERC721.sol | 1 - contracts/token/ERC721/IERC721Enumerable.sol | 1 - contracts/token/ERC721/IERC721Full.sol | 1 - contracts/token/ERC721/IERC721Metadata.sol | 1 - contracts/token/ERC721/IERC721Receiver.sol | 1 - contracts/utils/Address.sol | 1 - contracts/utils/ReentrancyGuard.sol | 1 - 110 files changed, 1 insertion(+), 131 deletions(-) diff --git a/.soliumrc.json b/.soliumrc.json index be4afce10..8fe25b30e 100644 --- a/.soliumrc.json +++ b/.soliumrc.json @@ -2,6 +2,7 @@ "extends": "solium:all", "plugins": ["security"], "rules": { + "blank-lines": "off", "error-reason": "off", "indentation": ["error", 2], "lbrace": "off", diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index b0212c2be..930a62066 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Roles * @dev Library for managing addresses assigned to a Role. diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index a37a119e8..756cdd48f 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract CapperRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index 74b22ccf3..cc95473c7 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract MinterRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index e6c4e6da7..06347e7cf 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract PauserRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index a6ab48305..e2729a255 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract SignerRole { using Roles for Roles.Role; diff --git a/contracts/bounties/BreakInvariantBounty.sol b/contracts/bounties/BreakInvariantBounty.sol index 58d725980..016d3f2f5 100644 --- a/contracts/bounties/BreakInvariantBounty.sol +++ b/contracts/bounties/BreakInvariantBounty.sol @@ -1,10 +1,8 @@ pragma solidity ^0.4.24; - import "../payment/PullPayment.sol"; import "../ownership/Ownable.sol"; - /** * @title BreakInvariantBounty * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. @@ -70,7 +68,6 @@ contract BreakInvariantBounty is PullPayment, Ownable { } - /** * @title Target * @dev Your main contract should inherit from this class and implement the checkInvariant method. diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index dd036a352..c1302ede4 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -4,7 +4,6 @@ import "../token/ERC20/IERC20.sol"; import "../math/SafeMath.sol"; import "../token/ERC20/SafeERC20.sol"; - /** * @title Crowdsale * @dev Crowdsale is a base contract for managing a token crowdsale, diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index c6995a44d..37d205c8e 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../validation/TimedCrowdsale.sol"; - /** * @title FinalizableCrowdsale * @dev Extension of Crowdsale with a one-off finalization action, where one diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index 5a7d89c7e..da9392aed 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -4,7 +4,6 @@ import "../validation/TimedCrowdsale.sol"; import "../../token/ERC20/IERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title PostDeliveryCrowdsale * @dev Crowdsale that locks tokens from withdrawal until it ends. diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index 80db88d41..a69d4a0ed 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -1,11 +1,9 @@ pragma solidity ^0.4.24; - import "../../math/SafeMath.sol"; import "./FinalizableCrowdsale.sol"; import "../../payment/RefundEscrow.sol"; - /** * @title RefundableCrowdsale * @dev Extension of Crowdsale contract that adds a funding goal, and diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index 2af6752fb..736635e0b 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -5,7 +5,6 @@ import "../../token/ERC20/IERC20.sol"; import "../../token/ERC20/SafeERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title AllowanceCrowdsale * @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale. diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index a57c7b807..62b03189a 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../Crowdsale.sol"; import "../../token/ERC20/ERC20Mintable.sol"; - /** * @title MintedCrowdsale * @dev Extension of Crowdsale contract whose tokens are minted in each purchase. diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 2d07c6763..386c6202b 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../validation/TimedCrowdsale.sol"; import "../../math/SafeMath.sol"; - /** * @title IncreasingPriceCrowdsale * @dev Extension of Crowdsale contract that increases the price of tokens linearly in time. diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 67a7d7c92..21708c34a 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; - /** * @title CappedCrowdsale * @dev Crowdsale with a limit for total contributions. diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index d2033984f..d00cb602e 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -4,7 +4,6 @@ import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; import "../../access/roles/CapperRole.sol"; - /** * @title IndividuallyCappedCrowdsale * @dev Crowdsale with per-beneficiary caps. diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index abbf1d116..098112cae 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; - /** * @title TimedCrowdsale * @dev Crowdsale accepting contributions only within a time frame. diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 61d19f20c..3f0ad1bd2 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Elliptic curve signature operations * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d diff --git a/contracts/cryptography/MerkleProof.sol b/contracts/cryptography/MerkleProof.sol index d490e7ff5..a0c304c57 100644 --- a/contracts/cryptography/MerkleProof.sol +++ b/contracts/cryptography/MerkleProof.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title MerkleProof * @dev Merkle proof verification based on diff --git a/contracts/drafts/Counter.sol b/contracts/drafts/Counter.sol index b47d9b824..3557bd744 100644 --- a/contracts/drafts/Counter.sol +++ b/contracts/drafts/Counter.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Counter * @author Matt Condon (@shrugs) diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index a85dac1f3..85b6ec671 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../token/ERC20/IERC20.sol"; - /** * @title ERC-1047 Token Metadata * @dev See https://eips.ethereum.org/EIPS/eip-1046 @@ -13,7 +12,6 @@ contract ERC20TokenMetadata is IERC20 { function tokenURI() external view returns (string); } - contract ERC20WithMetadata is ERC20TokenMetadata { string private _tokenURI = ""; diff --git a/contracts/drafts/ERC20Migrator.sol b/contracts/drafts/ERC20Migrator.sol index 69e745f14..44ed16423 100644 --- a/contracts/drafts/ERC20Migrator.sol +++ b/contracts/drafts/ERC20Migrator.sol @@ -5,7 +5,6 @@ import "../token/ERC20/ERC20Mintable.sol"; import "../token/ERC20/SafeERC20.sol"; import "../math/Math.sol"; - /** * @title ERC20Migrator * @dev This contract can be used to migrate an ERC20 token from one diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index a584b7aad..ff596b006 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../access/roles/SignerRole.sol"; import "../cryptography/ECDSA.sol"; - /** * @title SignatureBouncer * @author PhABC, Shrugs and aflesher diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 75b2aaa66..b97b60b2b 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -6,7 +6,6 @@ import "../token/ERC20/SafeERC20.sol"; import "../ownership/Ownable.sol"; import "../math/SafeMath.sol"; - /** * @title TokenVesting * @dev A token holder contract that can release its token balance gradually like a diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 293a9e438..6e1272223 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -5,7 +5,6 @@ import "../crowdsale/distribution/RefundableCrowdsale.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; import "../token/ERC20/ERC20Mintable.sol"; - /** * @title SampleCrowdsaleToken * @dev Very simple ERC20 Token that can be minted. @@ -18,7 +17,6 @@ contract SampleCrowdsaleToken is ERC20Mintable { uint8 public constant decimals = 18; } - /** * @title SampleCrowdsale * @dev This is an example of a fully fledged crowdsale. diff --git a/contracts/examples/SimpleToken.sol b/contracts/examples/SimpleToken.sol index 67de00ca4..8c63fdd98 100644 --- a/contracts/examples/SimpleToken.sol +++ b/contracts/examples/SimpleToken.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../token/ERC20/ERC20.sol"; - /** * @title SimpleToken * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 849cdf0c1..1af78d111 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC165.sol"; - /** * @title ERC165 * @author Matt Condon (@shrugs) diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 36bc20959..3491df904 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC165Checker * @dev Use `using ERC165Checker for address`; to include this library @@ -16,7 +15,6 @@ library ERC165Checker { * bytes4(keccak256('supportsInterface(bytes4)')) */ - /** * @notice Query if a contract supports ERC165 * @param account The address of the contract to query for support of ERC165 diff --git a/contracts/introspection/IERC165.sol b/contracts/introspection/IERC165.sol index 4d8b5b69f..4e4b7bbf6 100644 --- a/contracts/introspection/IERC165.sol +++ b/contracts/introspection/IERC165.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title IERC165 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 6d5aec994..5287ecdcb 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/PauserRole.sol"; - /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. @@ -13,7 +12,6 @@ contract Pausable is PauserRole { bool private _paused = false; - /** * @return true if the contract is paused, false otherwise. */ diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index 78ef1ae2b..d51a720c9 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Math * @dev Assorted math operations diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index d183fa361..97494e1f1 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title SafeMath * @dev Math operations with safety checks that revert on error diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol index b46fd06c3..e29396056 100644 --- a/contracts/mocks/AddressImpl.sol +++ b/contracts/mocks/AddressImpl.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../utils/Address.sol"; - contract AddressImpl { function isContract(address account) external diff --git a/contracts/mocks/AllowanceCrowdsaleImpl.sol b/contracts/mocks/AllowanceCrowdsaleImpl.sol index be01ccdf9..5b2104e38 100644 --- a/contracts/mocks/AllowanceCrowdsaleImpl.sol +++ b/contracts/mocks/AllowanceCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/emission/AllowanceCrowdsale.sol"; - contract AllowanceCrowdsaleImpl is AllowanceCrowdsale { constructor ( diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index e92cec204..176033b7f 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/CappedCrowdsale.sol"; - contract CappedCrowdsaleImpl is CappedCrowdsale { constructor ( diff --git a/contracts/mocks/CapperRoleMock.sol b/contracts/mocks/CapperRoleMock.sol index 05c15c9dd..118058f39 100644 --- a/contracts/mocks/CapperRoleMock.sol +++ b/contracts/mocks/CapperRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/CapperRole.sol"; - contract CapperRoleMock is CapperRole { function removeCapper(address account) public { _removeCapper(account); diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index d3723ad7d..93a594b97 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../payment/ConditionalEscrow.sol"; - // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { mapping(address => bool) private _allowed; diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol index d42fcbda2..3c958ba97 100644 --- a/contracts/mocks/CounterImpl.sol +++ b/contracts/mocks/CounterImpl.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../drafts/Counter.sol"; - contract CounterImpl { using Counter for Counter.Counter; diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index 082c451be..eea706326 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; - contract ERC20DetailedMock is ERC20, ERC20Detailed { constructor( string name, diff --git a/contracts/mocks/ECDSAMock.sol b/contracts/mocks/ECDSAMock.sol index fa3f22348..9f489069f 100644 --- a/contracts/mocks/ECDSAMock.sol +++ b/contracts/mocks/ECDSAMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../cryptography/ECDSA.sol"; - contract ECDSAMock { using ECDSA for bytes32; diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 6573d972c..1a06e9d52 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../introspection/IERC165.sol"; - /** * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md#specification * > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead throw an exception. @@ -56,8 +55,6 @@ contract SupportsInterfaceWithLookupMock is IERC165 { } } - - contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock { constructor (bytes4[] interfaceIds) public diff --git a/contracts/mocks/ERC165/ERC165NotSupported.sol b/contracts/mocks/ERC165/ERC165NotSupported.sol index 763f8faba..156ef8e8b 100644 --- a/contracts/mocks/ERC165/ERC165NotSupported.sol +++ b/contracts/mocks/ERC165/ERC165NotSupported.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - contract ERC165NotSupported { } diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index f4d6219f9..b0728ba15 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../introspection/ERC165Checker.sol"; - contract ERC165CheckerMock { using ERC165Checker for address; diff --git a/contracts/mocks/ERC165Mock.sol b/contracts/mocks/ERC165Mock.sol index cbedcdb74..c42ba62f2 100644 --- a/contracts/mocks/ERC165Mock.sol +++ b/contracts/mocks/ERC165Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../introspection/ERC165.sol"; - contract ERC165Mock is ERC165 { function registerInterface(bytes4 interfaceId) public diff --git a/contracts/mocks/ERC20BurnableMock.sol b/contracts/mocks/ERC20BurnableMock.sol index bbc7c4d1a..2c8b3b54a 100644 --- a/contracts/mocks/ERC20BurnableMock.sol +++ b/contracts/mocks/ERC20BurnableMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Burnable.sol"; - contract ERC20BurnableMock is ERC20Burnable { constructor(address initialAccount, uint256 initialBalance) public { diff --git a/contracts/mocks/ERC20MintableMock.sol b/contracts/mocks/ERC20MintableMock.sol index a2056548f..31384c790 100644 --- a/contracts/mocks/ERC20MintableMock.sol +++ b/contracts/mocks/ERC20MintableMock.sol @@ -3,6 +3,5 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "./MinterRoleMock.sol"; - contract ERC20MintableMock is ERC20Mintable, MinterRoleMock { } diff --git a/contracts/mocks/ERC20Mock.sol b/contracts/mocks/ERC20Mock.sol index 046730750..ab0877653 100644 --- a/contracts/mocks/ERC20Mock.sol +++ b/contracts/mocks/ERC20Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; - // mock class using ERC20 contract ERC20Mock is ERC20 { diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index c4aa05d06..c6c0fd5ed 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Pausable.sol"; import "./PauserRoleMock.sol"; - // mock class using ERC20Pausable contract ERC20PausableMock is ERC20Pausable, PauserRoleMock { diff --git a/contracts/mocks/ERC20WithMetadataMock.sol b/contracts/mocks/ERC20WithMetadataMock.sol index cdc1fe365..ec2d122a1 100644 --- a/contracts/mocks/ERC20WithMetadataMock.sol +++ b/contracts/mocks/ERC20WithMetadataMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; import "../drafts/ERC1046/TokenMetadata.sol"; - contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { constructor(string tokenURI) public ERC20WithMetadata(tokenURI) diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index e3f79b08f..d555b1f83 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -4,7 +4,6 @@ import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; - /** * @title ERC721Mock * This mock just provides a public mint and burn functions for testing purposes, diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index 4d3c962d8..03ff3ac37 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -4,7 +4,6 @@ import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; - /** * @title ERC721MintableBurnableImpl */ diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index 607ceed13..514d3bdbe 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721.sol"; - /** * @title ERC721Mock * This mock just provides a public mint and burn functions for testing purposes diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index 0efcbb925..9751d04cb 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721Pausable.sol"; import "./PauserRoleMock.sol"; - /** * @title ERC721PausableMock * This mock just provides a public mint, burn and exists functions for testing purposes diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 4e21ff6ac..57fb04e3a 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/IERC721Receiver.sol"; - contract ERC721ReceiverMock is IERC721Receiver { bytes4 private _retval; bool private _reverts; diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 20076bdd1..084780b1d 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/FinalizableCrowdsale.sol"; - contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { constructor ( diff --git a/contracts/mocks/ForceEther.sol b/contracts/mocks/ForceEther.sol index 41cde563c..bca5646f3 100644 --- a/contracts/mocks/ForceEther.sol +++ b/contracts/mocks/ForceEther.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - // @title Force Ether into a contract. // @notice even // if the contract is not payable. diff --git a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol index 29d71ec8a..6f1f2e2a0 100644 --- a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol +++ b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../crowdsale/price/IncreasingPriceCrowdsale.sol"; import "../math/SafeMath.sol"; - contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale { constructor ( diff --git a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol index d47600f8d..1bcb95301 100644 --- a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol +++ b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol @@ -4,7 +4,6 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol"; import "./CapperRoleMock.sol"; - contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock { diff --git a/contracts/mocks/InsecureInvariantTargetBounty.sol b/contracts/mocks/InsecureInvariantTargetBounty.sol index ded818b1a..cac749d63 100644 --- a/contracts/mocks/InsecureInvariantTargetBounty.sol +++ b/contracts/mocks/InsecureInvariantTargetBounty.sol @@ -5,14 +5,12 @@ pragma solidity ^0.4.24; // solium-disable-next-line max-len import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; - contract InsecureInvariantTargetMock is Target { function checkInvariant() public returns(bool) { return false; } } - contract InsecureInvariantTargetBounty is BreakInvariantBounty { function _deployContract() internal returns (address) { return new InsecureInvariantTargetMock(); diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index 696653858..72f7fc204 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../math/Math.sol"; - contract MathMock { function max(uint256 a, uint256 b) public pure returns (uint256) { return Math.max(a, b); diff --git a/contracts/mocks/MerkleProofWrapper.sol b/contracts/mocks/MerkleProofWrapper.sol index 7909098f6..b359dc790 100644 --- a/contracts/mocks/MerkleProofWrapper.sol +++ b/contracts/mocks/MerkleProofWrapper.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import { MerkleProof } from "../cryptography/MerkleProof.sol"; - contract MerkleProofWrapper { function verify( diff --git a/contracts/mocks/MessageHelper.sol b/contracts/mocks/MessageHelper.sol index 63571714f..54c084414 100644 --- a/contracts/mocks/MessageHelper.sol +++ b/contracts/mocks/MessageHelper.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - contract MessageHelper { event Show(bytes32 b32, uint256 number, string text); diff --git a/contracts/mocks/MintedCrowdsaleImpl.sol b/contracts/mocks/MintedCrowdsaleImpl.sol index afdd3b8c7..518371b75 100644 --- a/contracts/mocks/MintedCrowdsaleImpl.sol +++ b/contracts/mocks/MintedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; - contract MintedCrowdsaleImpl is MintedCrowdsale { constructor ( diff --git a/contracts/mocks/MinterRoleMock.sol b/contracts/mocks/MinterRoleMock.sol index bedf3d45f..45e5a4195 100644 --- a/contracts/mocks/MinterRoleMock.sol +++ b/contracts/mocks/MinterRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/MinterRole.sol"; - contract MinterRoleMock is MinterRole { function removeMinter(address account) public { _removeMinter(account); diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index a1c24c087..72ec843ed 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -1,10 +1,8 @@ pragma solidity ^0.4.24; - import "../lifecycle/Pausable.sol"; import "./PauserRoleMock.sol"; - // mock class using Pausable contract PausableMock is Pausable, PauserRoleMock { bool public drasticMeasureTaken; diff --git a/contracts/mocks/PauserRoleMock.sol b/contracts/mocks/PauserRoleMock.sol index df0213326..267101e4a 100644 --- a/contracts/mocks/PauserRoleMock.sol +++ b/contracts/mocks/PauserRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/PauserRole.sol"; - contract PauserRoleMock is PauserRole { function removePauser(address account) public { _removePauser(account); diff --git a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol index c6dca89a5..98d056c66 100644 --- a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/PostDeliveryCrowdsale.sol"; - contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale { constructor ( diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index d6da3ed70..63076c904 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../payment/PullPayment.sol"; - // mock class using PullPayment contract PullPaymentMock is PullPayment { diff --git a/contracts/mocks/ReentrancyAttack.sol b/contracts/mocks/ReentrancyAttack.sol index 05ef748e7..96231de27 100644 --- a/contracts/mocks/ReentrancyAttack.sol +++ b/contracts/mocks/ReentrancyAttack.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - contract ReentrancyAttack { function callSender(bytes4 data) public { diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index 130a8fd90..474ecd433 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../utils/ReentrancyGuard.sol"; import "./ReentrancyAttack.sol"; - contract ReentrancyMock is ReentrancyGuard { uint256 public counter; diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index 631f29d04..a14dfbcb3 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; - contract RefundableCrowdsaleImpl is RefundableCrowdsale { constructor ( diff --git a/contracts/mocks/RolesMock.sol b/contracts/mocks/RolesMock.sol index cd2922289..bfcee20ee 100644 --- a/contracts/mocks/RolesMock.sol +++ b/contracts/mocks/RolesMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/Roles.sol"; - contract RolesMock { using Roles for Roles.Role; diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 0009fd01c..c80c762d9 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; - contract ERC20FailingMock is IERC20 { function totalSupply() public view returns (uint256) { return 0; @@ -30,7 +29,6 @@ contract ERC20FailingMock is IERC20 { } } - contract ERC20SucceedingMock is IERC20 { function totalSupply() public view returns (uint256) { return 0; @@ -57,7 +55,6 @@ contract ERC20SucceedingMock is IERC20 { } } - contract SafeERC20Helper { using SafeERC20 for IERC20; diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index c5464ec16..7ddf17e9f 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../math/SafeMath.sol"; - contract SafeMathMock { function mul(uint256 a, uint256 b) public pure returns (uint256) { diff --git a/contracts/mocks/SecondaryMock.sol b/contracts/mocks/SecondaryMock.sol index 6863112fa..268c12516 100644 --- a/contracts/mocks/SecondaryMock.sol +++ b/contracts/mocks/SecondaryMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../ownership/Secondary.sol"; - contract SecondaryMock is Secondary { function onlyPrimaryMock() public view onlyPrimary { } diff --git a/contracts/mocks/SecureInvariantTargetBounty.sol b/contracts/mocks/SecureInvariantTargetBounty.sol index 40f2de994..9f2525bf0 100644 --- a/contracts/mocks/SecureInvariantTargetBounty.sol +++ b/contracts/mocks/SecureInvariantTargetBounty.sol @@ -5,14 +5,12 @@ pragma solidity ^0.4.24; // solium-disable-next-line max-len import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; - contract SecureInvariantTargetMock is Target { function checkInvariant() public returns(bool) { return true; } } - contract SecureInvariantTargetBounty is BreakInvariantBounty { function _deployContract() internal returns (address) { return new SecureInvariantTargetMock(); diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index 1ac00bfa2..ad9494033 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../drafts/SignatureBouncer.sol"; import "./SignerRoleMock.sol"; - contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { function checkValidSignature(address account, bytes signature) public diff --git a/contracts/mocks/SignerRoleMock.sol b/contracts/mocks/SignerRoleMock.sol index ba71cdeaa..faf92db68 100644 --- a/contracts/mocks/SignerRoleMock.sol +++ b/contracts/mocks/SignerRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/SignerRole.sol"; - contract SignerRoleMock is SignerRole { function removeSigner(address account) public { _removeSigner(account); diff --git a/contracts/mocks/TimedCrowdsaleImpl.sol b/contracts/mocks/TimedCrowdsaleImpl.sol index 296484ed1..f16e5eb2a 100644 --- a/contracts/mocks/TimedCrowdsaleImpl.sol +++ b/contracts/mocks/TimedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/TimedCrowdsale.sol"; - contract TimedCrowdsaleImpl is TimedCrowdsale { constructor ( diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index e7d2810de..d8ede5cd2 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control @@ -9,14 +8,12 @@ pragma solidity ^0.4.24; contract Ownable { address private _owner; - event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); - /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index 055db51d5..d602d67ec 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Secondary * @dev A Secondary contract can only be used by its primary account (the one that created it) diff --git a/contracts/payment/ConditionalEscrow.sol b/contracts/payment/ConditionalEscrow.sol index 933243a25..645dad479 100644 --- a/contracts/payment/ConditionalEscrow.sol +++ b/contracts/payment/ConditionalEscrow.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./Escrow.sol"; - /** * @title ConditionalEscrow * @dev Base abstract escrow to only allow withdrawal if a condition is met. diff --git a/contracts/payment/Escrow.sol b/contracts/payment/Escrow.sol index 2e6c5565a..21f7d6edd 100644 --- a/contracts/payment/Escrow.sol +++ b/contracts/payment/Escrow.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; import "../ownership/Secondary.sol"; - /** * @title Escrow * @dev Base escrow contract, holds funds destinated to a payee until they diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 8399fa4e1..67ef8c667 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./Escrow.sol"; - /** * @title PullPayment * @dev Base contract supporting async send for pull payments. Inherit from this diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/RefundEscrow.sol index ae7f9c463..3eca6bbcf 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/RefundEscrow.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ConditionalEscrow.sol"; import "../ownership/Secondary.sol"; - /** * @title RefundEscrow * @dev Escrow that holds funds for a beneficiary, deposited from multiple parties. diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index 19df9b706..e0e057ae8 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; - /** * @title SplitPayment * @dev This contract can be used when payments need to be received by a group diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 34cb3f6ce..8fd420a29 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./IERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title Standard ERC20 token * diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index e49d5de2c..014dc7fa8 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; - /** * @title Burnable Token * @dev Token that can be irreversibly burned (destroyed). diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 1222034cd..0a73159b6 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC20Mintable.sol"; - /** * @title Capped token * @dev Mintable token with a token cap. diff --git a/contracts/token/ERC20/ERC20Detailed.sol b/contracts/token/ERC20/ERC20Detailed.sol index ba411aa1f..706dbfc46 100644 --- a/contracts/token/ERC20/ERC20Detailed.sol +++ b/contracts/token/ERC20/ERC20Detailed.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC20.sol"; - /** * @title ERC20Detailed token * @dev The decimals are only for visualization purposes. diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index 20cc200ed..d6bd9b5ea 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "../../access/roles/MinterRole.sol"; - /** * @title ERC20Mintable * @dev ERC20 minting logic diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index 32932355d..8e6aa881f 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "../../lifecycle/Pausable.sol"; - /** * @title Pausable token * @dev ERC20 modified with pausable transfers. diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index 34d68fd62..37e5a447c 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 48b15fba9..10c6ff2bc 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "./IERC20.sol"; - /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure. diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index 9989ce77a..55903482b 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./SafeERC20.sol"; - /** * @title TokenTimelock * @dev TokenTimelock is a token holder contract that will allow a diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 7501248d7..eeee146e2 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -6,7 +6,6 @@ import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; import "../../introspection/ERC165.sol"; - /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index 3195cd424..3fc0277e5 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; - contract ERC721Burnable is ERC721 { function burn(uint256 tokenId) public diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index a4cceed20..0a2797eed 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -4,7 +4,6 @@ import "./IERC721Enumerable.sol"; import "./ERC721.sol"; import "../../introspection/ERC165.sol"; - contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; diff --git a/contracts/token/ERC721/ERC721Full.sol b/contracts/token/ERC721/ERC721Full.sol index 6492a8ca1..293637501 100644 --- a/contracts/token/ERC721/ERC721Full.sol +++ b/contracts/token/ERC721/ERC721Full.sol @@ -4,7 +4,6 @@ import "./ERC721.sol"; import "./ERC721Enumerable.sol"; import "./ERC721Metadata.sol"; - /** * @title Full ERC721 Token * This implementation includes all the required and some optional functionality of the ERC721 standard diff --git a/contracts/token/ERC721/ERC721Holder.sol b/contracts/token/ERC721/ERC721Holder.sol index 67048598f..cf0e9ce55 100644 --- a/contracts/token/ERC721/ERC721Holder.sol +++ b/contracts/token/ERC721/ERC721Holder.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721Receiver.sol"; - contract ERC721Holder is IERC721Receiver { function onERC721Received( address, diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index b4f1da3ab..8334160aa 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -4,7 +4,6 @@ import "./ERC721.sol"; import "./IERC721Metadata.sol"; import "../../introspection/ERC165.sol"; - contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name string internal _name; diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index 39fb9761d..f7cd0e9f9 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC721Full.sol"; import "../../access/roles/MinterRole.sol"; - /** * @title ERC721Mintable * @dev ERC721 minting logic diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/ERC721Pausable.sol index c0cca9dcf..c66d9da1f 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/ERC721Pausable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; import "../../lifecycle/Pausable.sol"; - /** * @title ERC721 Non-Fungible Pausable token * @dev ERC721 modified with pausable transfers. diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index 1d4ac1de4..24bc6a242 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../introspection/IERC165.sol"; - /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Enumerable.sol b/contracts/token/ERC721/IERC721Enumerable.sol index b848b7b69..b772f2507 100644 --- a/contracts/token/ERC721/IERC721Enumerable.sol +++ b/contracts/token/ERC721/IERC721Enumerable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Full.sol b/contracts/token/ERC721/IERC721Full.sol index 10914dc23..90d8c21d8 100644 --- a/contracts/token/ERC721/IERC721Full.sol +++ b/contracts/token/ERC721/IERC721Full.sol @@ -4,7 +4,6 @@ import "./IERC721.sol"; import "./IERC721Enumerable.sol"; import "./IERC721Metadata.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, full implementation interface * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index ed7ab29d9..2e1521208 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol index 946582f7e..e692f7e2c 100644 --- a/contracts/token/ERC721/IERC721Receiver.sol +++ b/contracts/token/ERC721/IERC721Receiver.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index 1f27c93f1..92a43ff9c 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * Utility library of inline functions on addresses */ diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 7f232cce5..63da3a99e 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Helps contracts guard against reentrancy attacks. * @author Remco Bloemen , Eenae From 21198bf1c1161fabfd0299ecac491f45b702a056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 26 Sep 2018 11:36:41 -0300 Subject: [PATCH 015/205] Roles now emit events in construction and when renouncing. (#1329) * release candidate v2.0.0-rc.1 * fix linter error (cherry picked from commit c12a1c6898c5db300bfeceea50438b328601705d) * Roles now emit events in construction and when renouncing. --- contracts/access/roles/CapperRole.sol | 12 ++++++++---- contracts/access/roles/MinterRole.sol | 12 ++++++++---- contracts/access/roles/PauserRole.sol | 12 ++++++++---- contracts/access/roles/SignerRole.sol | 12 ++++++++---- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- test/access/roles/PublicRole.behavior.js | 5 +++++ 8 files changed, 40 insertions(+), 19 deletions(-) diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index 756cdd48f..a79e8e694 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -11,7 +11,7 @@ contract CapperRole { Roles.Role private cappers; constructor() public { - cappers.add(msg.sender); + _addCapper(msg.sender); } modifier onlyCapper() { @@ -24,12 +24,16 @@ contract CapperRole { } function addCapper(address account) public onlyCapper { - cappers.add(account); - emit CapperAdded(account); + _addCapper(account); } function renounceCapper() public { - cappers.remove(msg.sender); + _removeCapper(msg.sender); + } + + function _addCapper(address account) internal { + cappers.add(account); + emit CapperAdded(account); } function _removeCapper(address account) internal { diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index cc95473c7..d908e3004 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -11,7 +11,7 @@ contract MinterRole { Roles.Role private minters; constructor() public { - minters.add(msg.sender); + _addMinter(msg.sender); } modifier onlyMinter() { @@ -24,12 +24,16 @@ contract MinterRole { } function addMinter(address account) public onlyMinter { - minters.add(account); - emit MinterAdded(account); + _addMinter(account); } function renounceMinter() public { - minters.remove(msg.sender); + _removeMinter(msg.sender); + } + + function _addMinter(address account) internal { + minters.add(account); + emit MinterAdded(account); } function _removeMinter(address account) internal { diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index 06347e7cf..d59839d6b 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -11,7 +11,7 @@ contract PauserRole { Roles.Role private pausers; constructor() public { - pausers.add(msg.sender); + _addPauser(msg.sender); } modifier onlyPauser() { @@ -24,12 +24,16 @@ contract PauserRole { } function addPauser(address account) public onlyPauser { - pausers.add(account); - emit PauserAdded(account); + _addPauser(account); } function renouncePauser() public { - pausers.remove(msg.sender); + _removePauser(msg.sender); + } + + function _addPauser(address account) internal { + pausers.add(account); + emit PauserAdded(account); } function _removePauser(address account) internal { diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index e2729a255..bbf8fd36f 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -11,7 +11,7 @@ contract SignerRole { Roles.Role private signers; constructor() public { - signers.add(msg.sender); + _addSigner(msg.sender); } modifier onlySigner() { @@ -24,12 +24,16 @@ contract SignerRole { } function addSigner(address account) public onlySigner { - signers.add(account); - emit SignerAdded(account); + _addSigner(account); } function renounceSigner() public { - signers.remove(msg.sender); + _removeSigner(msg.sender); + } + + function _addSigner(address account) internal { + signers.add(account); + emit SignerAdded(account); } function _removeSigner(address account) internal { diff --git a/ethpm.json b/ethpm.json index 27a294726..bb2674762 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "1.12.0", + "version": "2.0.0-rc.1", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index 3fa9ab04e..29034359c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "1.12.0", + "version": "2.0.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d3eedb5c2..235e500ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "1.12.0", + "version": "2.0.0-rc.1", "description": "Secure Smart Contract library for Solidity", "files": [ "build", diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index 1e489a468..f1c723b78 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -89,6 +89,11 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role (await this.contract[`is${rolename}`](authorized)).should.equal(false); }); + it(`emits a ${rolename}Removed event`, async function () { + const { logs } = await this.contract[`renounce${rolename}`]({ from: authorized }); + expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); + }); + it('doesn\'t revert when renouncing unassigned role', async function () { await this.contract[`renounce${rolename}`]({ from: anyone }); }); From 396680b856d832aa94d28b462c0d5f378265e575 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 26 Sep 2018 09:00:08 -0600 Subject: [PATCH 016/205] Add the missing test for ERC721Holder (#1249) * Add the missing test for ERC721Holder * fix lint * Move the holder test to a separate file --- test/token/ERC721/ERC721Holder.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/token/ERC721/ERC721Holder.test.js diff --git a/test/token/ERC721/ERC721Holder.test.js b/test/token/ERC721/ERC721Holder.test.js new file mode 100644 index 000000000..9f6eb856a --- /dev/null +++ b/test/token/ERC721/ERC721Holder.test.js @@ -0,0 +1,19 @@ +const ERC721Holder = artifacts.require('ERC721Holder.sol'); +const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol'); + +require('chai') + .should(); + +contract('ERC721Holder', function ([creator]) { + it('receives an ERC721 token', async function () { + const token = await ERC721Mintable.new({ from: creator }); + const tokenId = 1; + await token.mint(creator, tokenId, { from: creator }); + + const receiver = await ERC721Holder.new(); + await token.approve(receiver.address, tokenId, { from: creator }); + await token.safeTransferFrom(creator, receiver.address, tokenId); + + (await token.ownerOf(tokenId)).should.be.equal(receiver.address); + }); +}); From db2e1d2c746164f7460c6f311d9dc9d7b916e18a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 26 Sep 2018 12:57:02 -0300 Subject: [PATCH 017/205] Removed assertions from Escrow and SplitPayment. (#1349) --- contracts/payment/Escrow.sol | 1 - contracts/payment/SplitPayment.sol | 1 - 2 files changed, 2 deletions(-) diff --git a/contracts/payment/Escrow.sol b/contracts/payment/Escrow.sol index 21f7d6edd..7fb118e3a 100644 --- a/contracts/payment/Escrow.sol +++ b/contracts/payment/Escrow.sol @@ -39,7 +39,6 @@ contract Escrow is Secondary { */ function withdraw(address payee) public onlyPrimary { uint256 payment = _deposits[payee]; - assert(address(this).balance >= payment); _deposits[payee] = 0; diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index e0e057ae8..8bfcc7690 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -84,7 +84,6 @@ contract SplitPayment { ); require(payment != 0); - assert(address(this).balance >= payment); _released[account] = _released[account].add(payment); _totalReleased = _totalReleased.add(payment); From 5fdeaa81d5bd68abbb8789c949da32d28209a85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 26 Sep 2018 16:05:43 -0300 Subject: [PATCH 018/205] Removed mintingFinished. (#1351) * Removed mintingFinished from ERC20Mintable. * Removed MintingFinished from ERC721Mintable. * Removed MintingFinished event. --- contracts/token/ERC20/ERC20Mintable.sol | 32 ----- contracts/token/ERC721/ERC721Mintable.sol | 33 ----- .../ERC20/behaviors/ERC20Mintable.behavior.js | 134 +++--------------- test/token/ERC721/ERC721MintBurn.behavior.js | 29 ---- 4 files changed, 21 insertions(+), 207 deletions(-) diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index d6bd9b5ea..386abf64d 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -8,22 +8,6 @@ import "../../access/roles/MinterRole.sol"; * @dev ERC20 minting logic */ contract ERC20Mintable is ERC20, MinterRole { - event MintingFinished(); - - bool private _mintingFinished = false; - - modifier onlyBeforeMintingFinished() { - require(!_mintingFinished); - _; - } - - /** - * @return true if the minting is finished. - */ - function mintingFinished() public view returns(bool) { - return _mintingFinished; - } - /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. @@ -36,25 +20,9 @@ contract ERC20Mintable is ERC20, MinterRole { ) public onlyMinter - onlyBeforeMintingFinished returns (bool) { _mint(to, amount); return true; } - - /** - * @dev Function to stop minting new tokens. - * @return True if the operation was successful. - */ - function finishMinting() - public - onlyMinter - onlyBeforeMintingFinished - returns (bool) - { - _mintingFinished = true; - emit MintingFinished(); - return true; - } } diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index f7cd0e9f9..9dc0ad751 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -8,22 +8,6 @@ import "../../access/roles/MinterRole.sol"; * @dev ERC721 minting logic */ contract ERC721Mintable is ERC721Full, MinterRole { - event MintingFinished(); - - bool private _mintingFinished = false; - - modifier onlyBeforeMintingFinished() { - require(!_mintingFinished); - _; - } - - /** - * @return true if the minting is finished. - */ - function mintingFinished() public view returns(bool) { - return _mintingFinished; - } - /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. @@ -36,7 +20,6 @@ contract ERC721Mintable is ERC721Full, MinterRole { ) public onlyMinter - onlyBeforeMintingFinished returns (bool) { _mint(to, tokenId); @@ -50,26 +33,10 @@ contract ERC721Mintable is ERC721Full, MinterRole { ) public onlyMinter - onlyBeforeMintingFinished returns (bool) { mint(to, tokenId); _setTokenURI(tokenId, tokenURI); return true; } - - /** - * @dev Function to stop minting new tokens. - * @return True if the operation was successful. - */ - function finishMinting() - public - onlyMinter - onlyBeforeMintingFinished - returns (bool) - { - _mintingFinished = true; - emit MintingFinished(); - return true; - } } diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index 5046fc62e..16126d99a 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -11,136 +11,44 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; describe('as a mintable token', function () { - describe('mintingFinished', function () { - context('when token minting is not finished', function () { - it('returns false', async function () { - (await this.token.mintingFinished()).should.equal(false); - }); - }); - - context('when token minting is finished', function () { - beforeEach(async function () { - await this.token.finishMinting({ from: minter }); - }); - - it('returns true', async function () { - (await this.token.mintingFinished()).should.equal(true); - }); - }); - }); - - describe('finishMinting', function () { - context('when the sender has minting permission', function () { - const from = minter; - - context('when token minting was not finished', function () { - it('finishes token minting', async function () { - await this.token.finishMinting({ from }); - - (await this.token.mintingFinished()).should.equal(true); - }); - - it('emits a mint finished event', async function () { - const { logs } = await this.token.finishMinting({ from }); - - await expectEvent.inLogs(logs, 'MintingFinished'); - }); - }); - - context('when token minting was already finished', function () { - beforeEach(async function () { - await this.token.finishMinting({ from }); - }); - - it('reverts', async function () { - await assertRevert(this.token.finishMinting({ from })); - }); - }); - }); - - context('when the sender doesn\'t have minting permission', function () { - const from = anyone; - - context('when token minting was not finished', function () { - it('reverts', async function () { - await assertRevert(this.token.finishMinting({ from })); - }); - }); - - context('when token minting was already finished', function () { - beforeEach(async function () { - await this.token.finishMinting({ from: minter }); - }); - - it('reverts', async function () { - await assertRevert(this.token.finishMinting({ from })); - }); - }); - }); - }); - describe('mint', function () { const amount = 100; context('when the sender has minting permission', function () { const from = minter; - context('when token minting is not finished', function () { - context('for a zero amount', function () { - shouldMint(0); - }); - - context('for a non-zero amount', function () { - shouldMint(amount); - }); - - function shouldMint (amount) { - beforeEach(async function () { - ({ logs: this.logs } = await this.token.mint(anyone, amount, { from })); - }); - - it('mints the requested amount', async function () { - (await this.token.balanceOf(anyone)).should.be.bignumber.equal(amount); - }); - - it('emits a mint and a transfer event', async function () { - const transferEvent = expectEvent.inLogs(this.logs, 'Transfer', { - from: ZERO_ADDRESS, - to: anyone, - }); - transferEvent.args.value.should.be.bignumber.equal(amount); - }); - } + context('for a zero amount', function () { + shouldMint(0); }); - context('when token minting is finished', function () { + context('for a non-zero amount', function () { + shouldMint(amount); + }); + + function shouldMint (amount) { beforeEach(async function () { - await this.token.finishMinting({ from: minter }); + ({ logs: this.logs } = await this.token.mint(anyone, amount, { from })); }); - it('reverts', async function () { - await assertRevert(this.token.mint(anyone, amount, { from })); + it('mints the requested amount', async function () { + (await this.token.balanceOf(anyone)).should.be.bignumber.equal(amount); }); - }); + + it('emits a mint and a transfer event', async function () { + const transferEvent = expectEvent.inLogs(this.logs, 'Transfer', { + from: ZERO_ADDRESS, + to: anyone, + }); + transferEvent.args.value.should.be.bignumber.equal(amount); + }); + } }); context('when the sender doesn\'t have minting permission', function () { const from = anyone; - context('when token minting is not finished', function () { - it('reverts', async function () { - await assertRevert(this.token.mint(anyone, amount, { from })); - }); - }); - - context('when token minting is already finished', function () { - beforeEach(async function () { - await this.token.finishMinting({ from: minter }); - }); - - it('reverts', async function () { - await assertRevert(this.token.mint(anyone, amount, { from })); - }); + it('reverts', async function () { + await assertRevert(this.token.mint(anyone, amount, { from })); }); }); }); diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index cadfe87cc..31db1d176 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -117,35 +117,6 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); }); }); - - describe('finishMinting', function () { - it('allows the minter to finish minting', async function () { - const { logs } = await this.token.finishMinting({ from: minter }); - expectEvent.inLogs(logs, 'MintingFinished'); - }); - }); - - context('mintingFinished', function () { - beforeEach(async function () { - await this.token.finishMinting({ from: minter }); - }); - - describe('mint', function () { - it('reverts', async function () { - await assertRevert( - this.token.mint(owner, thirdTokenId, { from: minter }) - ); - }); - }); - - describe('mintWithTokenURI', function () { - it('reverts', async function () { - await assertRevert( - this.token.mintWithTokenURI(owner, thirdTokenId, MOCK_URI, { from: minter }) - ); - }); - }); - }); }); } From ae109f69ccf4b7264d8ca3dc0d2c9b658744bc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 26 Sep 2018 16:32:50 -0300 Subject: [PATCH 019/205] Improved bounty tests. (#1350) * Improved bounty tests. * Fixed linter errors. * Addressed review comments. --- ...ounty.sol => BreakInvariantBountyMock.sol} | 18 +- .../mocks/InsecureInvariantTargetBounty.sol | 18 -- test/BreakInvariantBounty.test.js | 159 +++++++++--------- 3 files changed, 97 insertions(+), 98 deletions(-) rename contracts/mocks/{SecureInvariantTargetBounty.sol => BreakInvariantBountyMock.sol} (51%) delete mode 100644 contracts/mocks/InsecureInvariantTargetBounty.sol diff --git a/contracts/mocks/SecureInvariantTargetBounty.sol b/contracts/mocks/BreakInvariantBountyMock.sol similarity index 51% rename from contracts/mocks/SecureInvariantTargetBounty.sol rename to contracts/mocks/BreakInvariantBountyMock.sol index 9f2525bf0..9343ef012 100644 --- a/contracts/mocks/SecureInvariantTargetBounty.sol +++ b/contracts/mocks/BreakInvariantBountyMock.sol @@ -5,14 +5,24 @@ pragma solidity ^0.4.24; // solium-disable-next-line max-len import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; -contract SecureInvariantTargetMock is Target { - function checkInvariant() public returns(bool) { +contract TargetMock is Target { + bool private exploited; + + function exploitVulnerability() public { + exploited = true; + } + + function checkInvariant() public returns (bool) { + if (exploited) { + return false; + } + return true; } } -contract SecureInvariantTargetBounty is BreakInvariantBounty { +contract BreakInvariantBountyMock is BreakInvariantBounty { function _deployContract() internal returns (address) { - return new SecureInvariantTargetMock(); + return new TargetMock(); } } diff --git a/contracts/mocks/InsecureInvariantTargetBounty.sol b/contracts/mocks/InsecureInvariantTargetBounty.sol deleted file mode 100644 index cac749d63..000000000 --- a/contracts/mocks/InsecureInvariantTargetBounty.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.4.24; - -// When this line is split, truffle parsing fails. -// See: https://github.com/ethereum/solidity/issues/4871 -// solium-disable-next-line max-len -import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; - -contract InsecureInvariantTargetMock is Target { - function checkInvariant() public returns(bool) { - return false; - } -} - -contract InsecureInvariantTargetBounty is BreakInvariantBounty { - function _deployContract() internal returns (address) { - return new InsecureInvariantTargetMock(); - } -} diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index 94a5fa0f7..a29e85080 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -2,97 +2,104 @@ const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); const expectEvent = require('./helpers/expectEvent'); const { assertRevert } = require('./helpers/assertRevert'); -const SecureInvariantTargetBounty = artifacts.require('SecureInvariantTargetBounty'); -const InsecureInvariantTargetBounty = artifacts.require('InsecureInvariantTargetBounty'); +const BreakInvariantBountyMock = artifacts.require('BreakInvariantBountyMock'); +const TargetMock = artifacts.require('TargetMock'); require('chai') .use(require('chai-bignumber')(web3.BigNumber)) .should(); -const sendReward = async (from, to, value) => ethSendTransaction({ - from, - to, - value, -}); - const reward = new web3.BigNumber(web3.toWei(1, 'ether')); -contract('BreakInvariantBounty', function ([_, owner, researcher, nonTarget]) { - context('against secure contract', function () { - beforeEach(async function () { - this.bounty = await SecureInvariantTargetBounty.new({ from: owner }); - }); - - it('can set reward', async function () { - await sendReward(owner, this.bounty.address, reward); - - const balance = await ethGetBalance(this.bounty.address); - balance.should.be.bignumber.equal(reward); - }); - - context('with reward', function () { - beforeEach(async function () { - const result = await this.bounty.createTarget({ from: researcher }); - const event = expectEvent.inLogs(result.logs, 'TargetCreated'); - - this.targetAddress = event.args.createdAddress; - - await sendReward(owner, this.bounty.address, reward); - - const balance = await ethGetBalance(this.bounty.address); - balance.should.be.bignumber.equal(reward); - }); - - it('cannot claim reward', async function () { - await assertRevert( - this.bounty.claim(this.targetAddress, { from: researcher }), - ); - }); - }); +contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTarget]) { + beforeEach(async function () { + this.bounty = await BreakInvariantBountyMock.new({ from: owner }); }); - context('against broken contract', function () { + it('can set reward', async function () { + await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); + (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(reward); + }); + + context('with reward', function () { beforeEach(async function () { - this.bounty = await InsecureInvariantTargetBounty.new(); - - const result = await this.bounty.createTarget({ from: researcher }); - const event = expectEvent.inLogs(result.logs, 'TargetCreated'); - - this.targetAddress = event.args.createdAddress; - await sendReward(owner, this.bounty.address, reward); + await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); }); - it('can claim reward', async function () { - await this.bounty.claim(this.targetAddress, { from: researcher }); - const claim = await this.bounty.claimed(); + describe('destroy', function () { + it('returns all balance to the owner', async function () { + const ownerPreBalance = await ethGetBalance(owner); + await this.bounty.destroy({ from: owner, gasPrice: 0 }); + const ownerPostBalance = await ethGetBalance(owner); - claim.should.equal(true); - - const researcherPrevBalance = await ethGetBalance(researcher); - - await this.bounty.withdrawPayments(researcher, { gasPrice: 0 }); - const updatedBalance = await ethGetBalance(this.bounty.address); - updatedBalance.should.be.bignumber.equal(0); - - const researcherCurrBalance = await ethGetBalance(researcher); - researcherCurrBalance.sub(researcherPrevBalance).should.be.bignumber.equal(reward); - }); - - it('cannot claim reward from non-target', async function () { - await assertRevert( - this.bounty.claim(nonTarget, { from: researcher }) - ); - }); - - context('reward claimed', function () { - beforeEach(async function () { - await this.bounty.claim(this.targetAddress, { from: researcher }); + (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); + ownerPostBalance.sub(ownerPreBalance).should.be.bignumber.equal(reward); }); - it('should no longer be payable', async function () { - await assertRevert( - sendReward(owner, this.bounty.address, reward) - ); + it('reverts when called by anyone', async function () { + await assertRevert(this.bounty.destroy({ from: anyone })); + }); + }); + + describe('claim', function () { + it('is initially unclaimed', async function () { + (await this.bounty.claimed()).should.equal(false); + }); + + it('can create claimable target', async function () { + const { logs } = await this.bounty.createTarget({ from: researcher }); + expectEvent.inLogs(logs, 'TargetCreated'); + }); + + context('with target', async function () { + beforeEach(async function () { + const { logs } = await this.bounty.createTarget({ from: researcher }); + const event = expectEvent.inLogs(logs, 'TargetCreated'); + this.target = TargetMock.at(event.args.createdAddress); + }); + + context('before exploiting vulnerability', async function () { + it('reverts when claiming reward', async function () { + await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); + }); + }); + + context('after exploiting vulnerability', async function () { + beforeEach(async function () { + await this.target.exploitVulnerability({ from: researcher }); + }); + + it('sends the reward to the researcher', async function () { + await this.bounty.claim(this.target.address, { from: anyone }); + + const researcherPreBalance = await ethGetBalance(researcher); + await this.bounty.withdrawPayments(researcher); + const researcherPostBalance = await ethGetBalance(researcher); + + researcherPostBalance.sub(researcherPreBalance).should.be.bignumber.equal(reward); + (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); + }); + + context('after claiming', async function () { + beforeEach(async function () { + await this.bounty.claim(this.target.address, { from: researcher }); + }); + + it('is claimed', async function () { + (await this.bounty.claimed()).should.equal(true); + }); + + it('no longer accepts rewards', async function () { + await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); + }); + }); + }); + }); + + context('with non-target', function () { + it('reverts when claiming reward', async function () { + await assertRevert(this.bounty.claim(nonTarget, { from: researcher })); + }); }); }); }); From 947de54ceea3abe4783ac2e417b6d9bfb93d708e Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Wed, 26 Sep 2018 22:04:41 +0200 Subject: [PATCH 020/205] Add BigNumber support to expectEvent/inLogs (#1026) (#1338) * Add BigNumber support to expectEvent/inLogs (#1026) * switched direct logs array check to expectEvent method in AllowanceCrowdsale.test.js * Refactor expectEvent.inLogs function to use simple value number check * Introduced should.be.bignumber method to compare BigNumber values * Destructure transaction object to extract logs field --- test/crowdsale/AllowanceCrowdsale.test.js | 17 +++++++----- test/helpers/expectEvent.js | 32 ++++++++++++++--------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index c35707d6d..74f26bbf1 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,10 +1,11 @@ +const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -41,12 +42,14 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs( + logs, + 'TokensPurchased', + { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount }); }); it('should assign tokens to sender', async function () { diff --git a/test/helpers/expectEvent.js b/test/helpers/expectEvent.js index 37fa1083e..b857b6636 100644 --- a/test/helpers/expectEvent.js +++ b/test/helpers/expectEvent.js @@ -1,24 +1,18 @@ -const should = require('chai').should(); +const BigNumber = web3.BigNumber; +const should = require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); function inLogs (logs, eventName, eventArgs = {}) { const event = logs.find(function (e) { if (e.event === eventName) { - let matches = true; - for (const [k, v] of Object.entries(eventArgs)) { - if (e.args[k] !== v) { - matches = false; - } - } - - if (matches) { - return true; + contains(e.args, k, v); } + return true; } }); - should.exist(event); - return event; } @@ -27,6 +21,20 @@ async function inTransaction (tx, eventName, eventArgs = {}) { return inLogs(logs, eventName, eventArgs); } +function contains (args, key, value) { + if (isBigNumber(args[key])) { + args[key].should.be.bignumber.equal(value); + } else { + args[key].should.be.equal(value); + } +} + +function isBigNumber (object) { + return object.isBigNumber || + object instanceof BigNumber || + (object.constructor && object.constructor.name === 'BigNumber'); +} + module.exports = { inLogs, inTransaction, From 75c0a59bb484eb0f04ec76eb8fa287d758af8ee5 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 26 Sep 2018 14:36:45 -0600 Subject: [PATCH 021/205] Add missing tests to ECSDA (#1248) * fix: refactor sign.js and related tests * fix: remove unused dep * fix: update package.json correctly * Add missing tests to ECRecovery * fix lint * Reorganize the tests * Reuse signature * fix static errors * Apply suggestions by @frangion and @nventuro * Remove only * More suggestions * Remove unnecessary max-len * remove only --- test/library/ECDSA.test.js | 145 ++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 42 deletions(-) diff --git a/test/library/ECDSA.test.js b/test/library/ECDSA.test.js index 7fe705653..f8d333a5f 100644 --- a/test/library/ECDSA.test.js +++ b/test/library/ECDSA.test.js @@ -11,56 +11,117 @@ const WRONG_MESSAGE = web3.sha3('Nope'); contract('ECDSA', function ([_, anyone]) { beforeEach(async function () { - this.mock = await ECDSAMock.new(); + this.ecdsa = await ECDSAMock.new(); }); - it('recover v0', async function () { - // Signature generated outside ganache with method web3.eth.sign(signer, message) - const signer = '0x2cc1166f6212628a0deef2b33befb2187d35b86c'; - // eslint-disable-next-line max-len - const signature = '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be89200'; - (await this.mock.recover(TEST_MESSAGE, signature)).should.equal(signer); + context('recover with valid signature', function () { + context('with v0 signature', function () { + // Signature generated outside ganache with method web3.eth.sign(signer, message) + const signer = '0x2cc1166f6212628a0deef2b33befb2187d35b86c'; + // eslint-disable-next-line max-len + const signatureWithoutVersion = '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be892'; + + context('with 00 as version value', function () { + it('works', async function () { + const version = '00'; + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer); + }); + }); + + context('with 27 as version value', function () { + it('works', async function () { + const version = '1b'; // 27 = 1b. + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer); + }); + }); + + context('with wrong version', function () { + it('returns 0', async function () { + // The last two hex digits are the signature version. + // The only valid values are 0, 1, 27 and 28. + const version = '02'; + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal( + '0x0000000000000000000000000000000000000000'); + }); + }); + }); + + context('with v1 signature', function () { + const signer = '0x1e318623ab09fe6de3c9b8672098464aeda9100e'; + // eslint-disable-next-line max-len + const signatureWithoutVersion = '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e0'; + + context('with 01 as version value', function () { + it('works', async function () { + const version = '01'; + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer); + }); + }); + + context('with 28 signature', function () { + it('works', async function () { + const version = '1c'; // 28 = 1c. + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer); + }); + }); + + context('with wrong version', function () { + it('returns 0', async function () { + // The last two hex digits are the signature version. + // The only valid values are 0, 1, 27 and 28. + const version = '02'; + const signature = signatureWithoutVersion + version; + (await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal( + '0x0000000000000000000000000000000000000000'); + }); + }); + }); + + context('using web3.eth.sign', function () { + context('with correct signature', function () { + it('returns signer address', async function () { + // Create the signature + const signature = signMessage(anyone, TEST_MESSAGE); + + // Recover the signer address from the generated message and signature. + (await this.ecdsa.recover( + toEthSignedMessageHash(TEST_MESSAGE), + signature + )).should.equal(anyone); + }); + }); + + context('with wrong signature', function () { + it('does not return signer address', async function () { + // Create the signature + const signature = signMessage(anyone, TEST_MESSAGE); + + // Recover the signer address from the generated message and wrong signature. + (await this.ecdsa.recover(WRONG_MESSAGE, signature)).should.not.equal(anyone); + }); + }); + }); }); - it('recover v1', async function () { - // Signature generated outside ganache with method web3.eth.sign(signer, message) - const signer = '0x1e318623ab09fe6de3c9b8672098464aeda9100e'; - // eslint-disable-next-line max-len - const signature = '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e001'; - (await this.mock.recover(TEST_MESSAGE, signature)).should.equal(signer); - }); - - it('recover using web3.eth.sign()', async function () { - // Create the signature - const signature = signMessage(anyone, TEST_MESSAGE); - - // Recover the signer address from the generated message and signature. - (await this.mock.recover( - toEthSignedMessageHash(TEST_MESSAGE), - signature - )).should.equal(anyone); - }); - - it('recover using web3.eth.sign() should return wrong signer', async function () { - // Create the signature - const signature = signMessage(anyone, TEST_MESSAGE); - - // Recover the signer address from the generated message and wrong signature. - (await this.mock.recover(WRONG_MESSAGE, signature)).should.not.equal(anyone); - }); - - // @TODO - remove `skip` once we upgrade to solc^0.5 - it.skip('recover should revert when a small hash is sent', async function () { - // Create the signature - const signature = signMessage(anyone, TEST_MESSAGE); - await expectThrow( - this.mock.recover(TEST_MESSAGE.substring(2), signature) - ); + context('with small hash', function () { + // @TODO - remove `skip` once we upgrade to solc^0.5 + it.skip('reverts', async function () { + // Create the signature + const signature = signMessage(anyone, TEST_MESSAGE); + await expectThrow( + this.ecdsa.recover(TEST_MESSAGE.substring(2), signature) + ); + }); }); context('toEthSignedMessage', function () { it('should prefix hashes correctly', async function () { - (await this.mock.toEthSignedMessageHash(TEST_MESSAGE)).should.equal(toEthSignedMessageHash(TEST_MESSAGE)); + (await this.ecdsa.toEthSignedMessageHash(TEST_MESSAGE)).should.equal(toEthSignedMessageHash(TEST_MESSAGE)); }); }); }); From 536262f2ec5d6103129283a023b467d8887adce3 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Thu, 27 Sep 2018 16:33:28 +0200 Subject: [PATCH 022/205] Feature/use expect event in test logs assertions #1232 (#1343) * Add BigNumber support to expectEvent/inLogs (#1026) * switched direct logs array check to expectEvent method in AllowanceCrowdsale.test.js * Refactor expectEvent.inLogs function to use simple value number check * Introduced should.be.bignumber method to compare BigNumber values * Use expectEvent to test logs (#1232) * Removed trailing space --- test/crowdsale/AllowanceCrowdsale.test.js | 14 ++-- test/crowdsale/Crowdsale.test.js | 27 +++---- test/crowdsale/FinalizableCrowdsale.test.js | 6 +- test/crowdsale/MintedCrowdsale.behavior.js | 15 ++-- test/payment/Escrow.behavior.js | 18 ++--- test/payment/RefundEscrow.test.js | 10 ++- test/token/ERC20/ERC20.test.js | 65 +++++++++-------- test/token/ERC20/ERC20Pausable.test.js | 7 +- .../ERC20/behaviors/ERC20Burnable.behavior.js | 18 ++--- .../ERC20/behaviors/ERC20Mintable.behavior.js | 4 +- test/token/ERC721/ERC721.behavior.js | 71 ++++++++++--------- test/token/ERC721/ERC721MintBurn.behavior.js | 14 ++-- 12 files changed, 135 insertions(+), 134 deletions(-) diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 74f26bbf1..8e57a841b 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -42,14 +42,12 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - expectEvent.inLogs( - logs, - 'TokensPurchased', - { - purchaser: investor, - beneficiary: investor, - value: value, - amount: expectedTokenAmount }); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 556855796..f691c9515 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,10 +1,11 @@ +const expectEvent = require('../helpers/expectEvent'); const { assertRevert } = require('../helpers/assertRevert'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -82,12 +83,12 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { @@ -106,12 +107,12 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { describe('low-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: purchaser, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to beneficiary', async function () { diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 187c67a36..b024fe1d4 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); const { increaseTimeTo, duration } = require('../helpers/increaseTime'); const { latestTime } = require('../helpers/latestTime'); @@ -6,7 +7,7 @@ const { EVMRevert } = require('../helpers/EVMRevert'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -50,7 +51,6 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { it('logs finalized', async function () { await increaseTimeTo(this.afterClosingTime); const { logs } = await this.crowdsale.finalize({ from: anyone }); - const event = logs.find(e => e.event === 'CrowdsaleFinalized'); - should.exist(event); + expectEvent.inLogs(logs, 'CrowdsaleFinalized'); }); }); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index f5d61328c..c55850cd9 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -1,8 +1,9 @@ +const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -20,12 +21,12 @@ function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 761aecd89..fce4bd692 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -31,10 +31,11 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('emits a deposited event', async function () { - const receipt = await this.escrow.deposit(payee1, { from: primary, value: amount }); - - const event = expectEvent.inLogs(receipt.logs, 'Deposited', { payee: payee1 }); - event.args.weiAmount.should.be.bignumber.equal(amount); + const { logs } = await this.escrow.deposit(payee1, { from: primary, value: amount }); + expectEvent.inLogs(logs, 'Deposited', { + payee: payee1, + weiAmount: amount + }); }); it('can add multiple deposits on a single account', async function () { @@ -83,10 +84,11 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { it('emits a withdrawn event', async function () { await this.escrow.deposit(payee1, { from: primary, value: amount }); - const receipt = await this.escrow.withdraw(payee1, { from: primary }); - - const event = expectEvent.inLogs(receipt.logs, 'Withdrawn', { payee: payee1 }); - event.args.weiAmount.should.be.bignumber.equal(amount); + const { logs } = await this.escrow.withdraw(payee1, { from: primary }); + expectEvent.inLogs(logs, 'Withdrawn', { + payee: payee1, + weiAmount: amount + }); }); }); }); diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index e412816c4..c499f4009 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -53,9 +53,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('only the primary account can enter closed state', async function () { await expectThrow(this.escrow.close({ from: beneficiary }), EVMRevert); - const receipt = await this.escrow.close({ from: primary }); - - expectEvent.inLogs(receipt.logs, 'Closed'); + const { logs } = await this.escrow.close({ from: primary }); + expectEvent.inLogs(logs, 'Closed'); }); context('closed state', function () { @@ -93,9 +92,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('only the primary account can enter refund state', async function () { await expectThrow(this.escrow.enableRefunds({ from: beneficiary }), EVMRevert); - const receipt = await this.escrow.enableRefunds({ from: primary }); - - expectEvent.inLogs(receipt.logs, 'RefundsEnabled'); + const { logs } = await this.escrow.enableRefunds({ from: primary }); + expectEvent.inLogs(logs, 'RefundsEnabled'); }); context('refund state', function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 3662a41a7..283e8752a 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -62,12 +62,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits a transfer event', async function () { const { logs } = await this.token.transfer(to, amount, { from: owner }); - const event = expectEvent.inLogs(logs, 'Transfer', { + expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, + value: amount }); - - event.args.value.should.be.bignumber.equal(amount); }); }); }); @@ -91,11 +90,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.approve(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -125,11 +124,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.approve(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -195,11 +194,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits a transfer event', async function () { const { logs } = await this.token.transferFrom(owner, to, amount, { from: spender }); - logs.length.should.equal(1); - logs[0].event.should.equal('Transfer'); - logs[0].args.from.should.equal(owner); - logs[0].args.to.should.equal(to); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: to, + value: amount + }); }); }); @@ -270,11 +269,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.decreaseAllowance(spender, approvedAmount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(0); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: 0 + }); }); it('decreases the spender allowance subtracting the requested amount', async function () { @@ -327,11 +326,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.increaseAllowance(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -361,11 +360,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.increaseAllowance(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index fa733a3f6..a524e2442 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../../helpers/expectEvent'); const { assertRevert } = require('../../helpers/assertRevert'); const ERC20PausableMock = artifacts.require('ERC20PausableMock'); @@ -30,8 +31,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('emits a Pause event', async function () { const { logs } = await this.token.pause({ from }); - logs.length.should.equal(1); - logs[0].event.should.equal('Paused'); + expectEvent.inLogs(logs, 'Paused'); }); }); @@ -72,8 +72,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('emits an Unpause event', async function () { const { logs } = await this.token.unpause({ from }); - logs.length.should.equal(1); - logs[0].event.should.equal('Unpaused'); + expectEvent.inLogs(logs, 'Unpaused'); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index cf0190046..9c7bada7a 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -29,10 +29,11 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { }); it('emits a transfer event', async function () { - const event = expectEvent.inLogs(this.logs, 'Transfer'); - event.args.from.should.equal(owner); - event.args.to.should.equal(ZERO_ADDRESS); - event.args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(this.logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + value: amount + }); }); } }); @@ -74,10 +75,11 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { }); it('emits a transfer event', async function () { - const event = expectEvent.inLogs(this.logs, 'Transfer'); - event.args.from.should.equal(owner); - event.args.to.should.equal(ZERO_ADDRESS); - event.args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(this.logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + value: amount + }); }); } }); diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index 16126d99a..07b3837b0 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -35,11 +35,11 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { }); it('emits a mint and a transfer event', async function () { - const transferEvent = expectEvent.inLogs(this.logs, 'Transfer', { + expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: anyone, + value: amount }); - transferEvent.args.value.should.be.bignumber.equal(amount); }); } }); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index ecdc3352f..d2cefe743 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,3 +1,4 @@ +const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const { assertRevert } = require('../../helpers/assertRevert'); const { decodeLogs } = require('../../helpers/decodeLogs'); @@ -88,19 +89,19 @@ function shouldBehaveLikeERC721 ( if (approved) { it('emit only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(this.toWhom); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: this.toWhom, + tokenId: tokenId + }); }); } else { it('emits only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(this.toWhom); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: this.toWhom, + tokenId: tokenId + }); }); } @@ -161,11 +162,11 @@ function shouldBehaveLikeERC721 ( }); it('emits only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(owner); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: owner, + tokenId: tokenId + }); }); it('keeps the owner balance', async function () { @@ -337,11 +338,11 @@ function shouldBehaveLikeERC721 ( const itEmitsApprovalEvent = function (address) { it('emits an approval event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Approval'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.approved.should.be.equal(address); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + approved: address, + tokenId: tokenId + }); }); }; @@ -447,11 +448,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); }); @@ -469,11 +470,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); it('can unset the operator approval', async function () { @@ -497,11 +498,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); }); }); diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index 31db1d176..a4289d27a 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -42,11 +42,11 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('emits a transfer and minted event', async function () { - await expectEvent.inLogs(logs, 'Transfer', { + expectEvent.inLogs(logs, 'Transfer', { from: ZERO_ADDRESS, to: newOwner, + tokenId: thirdTokenId }); - logs[0].args.tokenId.should.be.bignumber.equal(thirdTokenId); }); }); @@ -87,11 +87,11 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('emits a burn event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(ZERO_ADDRESS); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + tokenId: tokenId + }); }); }); From 1a4e5346ed40e5c02f5ca75d3cdfccb694c641d9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 27 Sep 2018 19:40:18 -0300 Subject: [PATCH 023/205] Add SignatureBouncer test for when msg.data is too short (#1360) * add test for msg.data too short * fix test to hit that branch * Update SignatureBouncer.test.js --- contracts/mocks/SignatureBouncerMock.sol | 7 +++++++ test/drafts/SignatureBouncer.test.js | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index ad9494033..85076eae6 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -63,4 +63,11 @@ contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { { } + + function tooShortMsgData() + public + onlyValidSignatureAndData("") + view + { + } } diff --git a/test/drafts/SignatureBouncer.test.js b/test/drafts/SignatureBouncer.test.js index b320ca98c..c234687fc 100644 --- a/test/drafts/SignatureBouncer.test.js +++ b/test/drafts/SignatureBouncer.test.js @@ -128,6 +128,12 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz ) ); }); + + it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () { + await assertRevert( + this.sigBouncer.tooShortMsgData({ from: authorizedUser }) + ); + }); }); }); From a6889776f46adca374b6ebf014aa7b0038112a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 28 Sep 2018 22:20:43 -0300 Subject: [PATCH 024/205] Dangling commas are now required. (#1359) --- .eslintrc | 2 +- test/crowdsale/AllowanceCrowdsale.test.js | 2 +- test/crowdsale/Crowdsale.test.js | 4 ++-- test/crowdsale/MintedCrowdsale.behavior.js | 2 +- test/payment/Escrow.behavior.js | 4 ++-- test/token/ERC20/ERC20.test.js | 14 +++++++------- .../ERC20/behaviors/ERC20Burnable.behavior.js | 4 ++-- .../ERC20/behaviors/ERC20Mintable.behavior.js | 2 +- test/token/ERC721/ERC721.behavior.js | 14 +++++++------- test/token/ERC721/ERC721MintBurn.behavior.js | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.eslintrc b/.eslintrc index 117135b36..c15a4d515 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,7 @@ // Code style "camelcase": ["error", {"properties": "always"}], - "comma-dangle": ["warn", "always-multiline"], + "comma-dangle": ["error", "always-multiline"], "comma-spacing": ["error", {"before": false, "after": true}], "dot-notation": ["error", {"allowKeywords": true, "allowPattern": ""}], "eol-last": ["error", "always"], diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 8e57a841b..c0ff4cd91 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -46,7 +46,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index f691c9515..4113f7cb4 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -87,7 +87,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); @@ -111,7 +111,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { purchaser: purchaser, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index c55850cd9..ab8dc8259 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -25,7 +25,7 @@ function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index fce4bd692..57f1fe5d0 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -34,7 +34,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { const { logs } = await this.escrow.deposit(payee1, { from: primary, value: amount }); expectEvent.inLogs(logs, 'Deposited', { payee: payee1, - weiAmount: amount + weiAmount: amount, }); }); @@ -87,7 +87,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { const { logs } = await this.escrow.withdraw(payee1, { from: primary }); expectEvent.inLogs(logs, 'Withdrawn', { payee: payee1, - weiAmount: amount + weiAmount: amount, }); }); }); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 283e8752a..e991c2ae6 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -65,7 +65,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, - value: amount + value: amount, }); }); }); @@ -93,7 +93,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -127,7 +127,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -197,7 +197,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, - value: amount + value: amount, }); }); }); @@ -272,7 +272,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: 0 + value: 0, }); }); @@ -329,7 +329,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -363,7 +363,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 9c7bada7a..c52594d18 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -32,7 +32,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { expectEvent.inLogs(this.logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount + value: amount, }); }); } @@ -78,7 +78,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { expectEvent.inLogs(this.logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount + value: amount, }); }); } diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index 07b3837b0..dbda9eeed 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -38,7 +38,7 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: anyone, - value: amount + value: amount, }); }); } diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index d2cefe743..ce56747de 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -92,7 +92,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: this.toWhom, - tokenId: tokenId + tokenId: tokenId, }); }); } else { @@ -100,7 +100,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: this.toWhom, - tokenId: tokenId + tokenId: tokenId, }); }); } @@ -165,7 +165,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: owner, - tokenId: tokenId + tokenId: tokenId, }); }); @@ -341,7 +341,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Approval', { owner: owner, approved: address, - tokenId: tokenId + tokenId: tokenId, }); }); }; @@ -451,7 +451,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); }); @@ -473,7 +473,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); @@ -501,7 +501,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); }); diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index a4289d27a..8aeccd5d8 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -45,7 +45,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: ZERO_ADDRESS, to: newOwner, - tokenId: thirdTokenId + tokenId: thirdTokenId, }); }); }); @@ -90,7 +90,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - tokenId: tokenId + tokenId: tokenId, }); }); }); From fa1dfbd113dee461ab9860514c9ad487fabfcfee Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 1 Oct 2018 18:09:57 +0530 Subject: [PATCH 025/205] Fix #1358 Test helper to send funds (#1367) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * fixes #1358 * linting done * suggested changes --- test/BreakInvariantBounty.test.js | 5 +++-- test/helpers/sendTransaction.js | 9 +++++++++ test/payment/SplitPayment.test.js | 9 +++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index a29e85080..4c1f8b06c 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -1,4 +1,5 @@ const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); +const { sendEther } = require('./helpers/sendTransaction'); const expectEvent = require('./helpers/expectEvent'); const { assertRevert } = require('./helpers/assertRevert'); @@ -17,13 +18,13 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); it('can set reward', async function () { - await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); + await sendEther(owner, this.bounty.address, reward); (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(reward); }); context('with reward', function () { beforeEach(async function () { - await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); + await sendEther(owner, this.bounty.address, reward); }); describe('destroy', function () { diff --git a/test/helpers/sendTransaction.js b/test/helpers/sendTransaction.js index e49376b44..9d4f3068f 100644 --- a/test/helpers/sendTransaction.js +++ b/test/helpers/sendTransaction.js @@ -15,7 +15,16 @@ function sendTransaction (target, name, argsTypes, argsValues, opts) { return target.sendTransaction(Object.assign({ data: encodedData }, opts)); } +function sendEther (from, to, value) { + web3.eth.sendTransaction({ + from: from, + to: to, + value: value, + gasPrice: 0, + }); +} module.exports = { findMethod, sendTransaction, + sendEther, }; diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index 05cc0b701..cf9ef0e01 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -1,4 +1,5 @@ -const { ethGetBalance, ethSendTransaction } = require('../helpers/web3'); +const { ethGetBalance } = require('../helpers/web3'); +const { sendEther } = require('./../helpers/sendTransaction'); const BigNumber = web3.BigNumber; @@ -58,7 +59,7 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should accept payments', async function () { - await ethSendTransaction({ from: owner, to: this.contract.address, value: amount }); + await sendEther(owner, this.contract.address, amount); (await ethGetBalance(this.contract.address)).should.be.bignumber.equal(amount); }); @@ -76,12 +77,12 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should throw if non-payee want to claim', async function () { - await ethSendTransaction({ from: payer1, to: this.contract.address, value: amount }); + await sendEther(payer1, this.contract.address, amount); await expectThrow(this.contract.release(nonpayee1), EVMRevert); }); it('should distribute funds to payees', async function () { - await ethSendTransaction({ from: payer1, to: this.contract.address, value: amount }); + await sendEther(payer1, this.contract.address, amount); // receive funds const initBalance = await ethGetBalance(this.contract.address); From 6ae041bca61ff2d6c25acc865b0152cf54122528 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 1 Oct 2018 20:53:47 +0530 Subject: [PATCH 026/205] Fix/#1355 test helper to check balance difference (#1368) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * fixex #1355 * linting * suggested changes * Update BreakInvariantBounty.test.js --- test/BreakInvariantBounty.test.js | 9 +++------ test/helpers/balanceDiff.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 test/helpers/balanceDiff.js diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index 4c1f8b06c..ff8e0f7bd 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -1,5 +1,6 @@ const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); const { sendEther } = require('./helpers/sendTransaction'); +const { balanceDifference } = require('./helpers/balanceDiff'); const expectEvent = require('./helpers/expectEvent'); const { assertRevert } = require('./helpers/assertRevert'); @@ -72,12 +73,8 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar it('sends the reward to the researcher', async function () { await this.bounty.claim(this.target.address, { from: anyone }); - - const researcherPreBalance = await ethGetBalance(researcher); - await this.bounty.withdrawPayments(researcher); - const researcherPostBalance = await ethGetBalance(researcher); - - researcherPostBalance.sub(researcherPreBalance).should.be.bignumber.equal(reward); + (await balanceDifference(researcher, () => this.bounty.withdrawPayments(researcher))) + .should.be.bignumber.equal(reward); (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); }); diff --git a/test/helpers/balanceDiff.js b/test/helpers/balanceDiff.js new file mode 100644 index 000000000..8f88ba400 --- /dev/null +++ b/test/helpers/balanceDiff.js @@ -0,0 +1,10 @@ +async function balanceDifference (account, promise) { + const balanceBefore = web3.eth.getBalance(account); + await promise(); + const balanceAfter = web3.eth.getBalance(account); + return balanceAfter.minus(balanceBefore); +} + +module.exports = { + balanceDifference, +}; From 34bc709bc2e5117cdd762e92a29ed88557532e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 07:07:11 -0300 Subject: [PATCH 027/205] Merged latestTime, increaseTime and duration into a time helper. (#1364) --- test/crowdsale/FinalizableCrowdsale.test.js | 15 ++++++------ .../IncreasingPriceCrowdsale.test.js | 23 +++++++++--------- test/crowdsale/PostDeliveryCrowdsale.test.js | 13 +++++----- test/crowdsale/RefundableCrowdsale.test.js | 15 ++++++------ test/crowdsale/TimedCrowdsale.test.js | 19 +++++++-------- test/examples/SampleCrowdsale.test.js | 23 +++++++++--------- test/helpers/latestTime.js | 11 --------- test/helpers/{increaseTime.js => time.js} | 21 ++++++++++------ test/token/ERC20/TokenTimelock.test.js | 15 ++++++------ test/token/ERC20/TokenVesting.test.js | 24 +++++++++---------- 10 files changed, 84 insertions(+), 95 deletions(-) delete mode 100644 test/helpers/latestTime.js rename test/helpers/{increaseTime.js => time.js} (78%) diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index b024fe1d4..6eea7f2f2 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,7 +1,6 @@ const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); @@ -23,9 +22,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await ERC20.new(); this.crowdsale = await FinalizableCrowdsaleImpl.new( @@ -38,18 +37,18 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); it('can be finalized by anyone after ending', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); it('cannot be finalized twice', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); }); it('logs finalized', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); const { logs } = await this.crowdsale.finalize({ from: anyone }); expectEvent.inLogs(logs, 'CrowdsaleFinalized'); }); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 767b5f8e5..2024d7751 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { assertRevert } = require('../helpers/assertRevert'); const BigNumber = web3.BigNumber; @@ -29,9 +28,9 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) beforeEach(async function () { await advanceBlock(); - this.startTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.startTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.startTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.startTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); }); @@ -61,43 +60,43 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('at start', async function () { - await increaseTimeTo(this.startTime); + await time.increaseTo(this.startTime); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(initialRate)); }); it('at time 150', async function () { - await increaseTimeTo(this.startTime + 150); + await time.increaseTo(this.startTime + 150); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime150)); }); it('at time 300', async function () { - await increaseTimeTo(this.startTime + 300); + await time.increaseTo(this.startTime + 300); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime300)); }); it('at time 1500', async function () { - await increaseTimeTo(this.startTime + 1500); + await time.increaseTo(this.startTime + 1500); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime1500)); }); it('at time 30', async function () { - await increaseTimeTo(this.startTime + 30); + await time.increaseTo(this.startTime + 30); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime30)); }); it('at time 150000', async function () { - await increaseTimeTo(this.startTime + 150000); + await time.increaseTo(this.startTime + 150000); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime150000)); }); it('at time 450000', async function () { - await increaseTimeTo(this.startTime + 450000); + await time.increaseTo(this.startTime + 450000); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime450000)); }); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 94ebd808b..866e4da15 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -1,6 +1,5 @@ const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ether } = require('../helpers/ether'); @@ -24,9 +23,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); this.crowdsale = await PostDeliveryCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address @@ -36,7 +35,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { context('after opening time', function () { beforeEach(async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); }); context('with bought tokens', function () { @@ -57,7 +56,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { context('after closing time', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); }); it('allows beneficiaries to withdraw tokens', async function () { diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 749ec5cac..77e0bfebb 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); @@ -27,9 +26,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.preWalletBalance = await ethGetBalance(wallet); this.token = await SimpleToken.new(); @@ -61,7 +60,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after opening time', function () { beforeEach(async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); }); it('denies refunds', async function () { @@ -75,7 +74,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after closing time and finalization', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); @@ -95,7 +94,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after closing time and finalization', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index df3e01c81..cfbc3d3cf 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); @@ -25,21 +24,21 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); }); it('rejects an opening time in the past', async function () { await expectThrow(TimedCrowdsaleImpl.new( - (await latestTime()) - duration.days(1), this.closingTime, rate, wallet, this.token.address + (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address ), EVMRevert); }); it('rejects a closing time before the opening time', async function () { await expectThrow(TimedCrowdsaleImpl.new( - this.openingTime, this.openingTime - duration.seconds(1), rate, wallet, this.token.address + this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address ), EVMRevert); }); @@ -53,7 +52,7 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { it('should be ended only after end', async function () { (await this.crowdsale.hasClosed()).should.equal(false); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); (await this.crowdsale.isOpen()).should.equal(false); (await this.crowdsale.hasClosed()).should.equal(true); }); @@ -66,14 +65,14 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('should accept payments after start', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); (await this.crowdsale.isOpen()).should.equal(true); await this.crowdsale.send(value); await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); }); it('should reject payments after end', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await expectThrow(this.crowdsale.send(value), EVMRevert); await expectThrow(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }), EVMRevert); }); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index e47143535..303ddf704 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { assertRevert } = require('../helpers/assertRevert'); @@ -27,9 +26,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SampleCrowdsaleToken.new({ from: deployer }); this.crowdsale = await SampleCrowdsale.new( @@ -68,7 +67,7 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { const investmentAmount = ether(1); const expectedTokenAmount = RATE.mul(investmentAmount); - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.buyTokens(investor, { value: investmentAmount, from: investor }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(expectedTokenAmount); @@ -76,23 +75,23 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); it('should reject payments after end', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await expectThrow(this.crowdsale.send(ether(1)), EVMRevert); await expectThrow(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor }), EVMRevert); }); it('should reject payments over cap', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.send(CAP); await expectThrow(this.crowdsale.send(1), EVMRevert); }); it('should allow finalization and transfer funds to wallet if the goal is reached', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.send(GOAL); const beforeFinalization = await ethGetBalance(wallet); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: owner }); const afterFinalization = await ethGetBalance(wallet); @@ -102,9 +101,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { it('should allow refunds if the goal is not reached', async function () { const balanceBeforeInvestment = await ethGetBalance(investor); - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.sendTransaction({ value: ether(1), from: investor, gasPrice: 0 }); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: owner }); await this.crowdsale.claimRefund(investor, { gasPrice: 0 }); diff --git a/test/helpers/latestTime.js b/test/helpers/latestTime.js deleted file mode 100644 index fee9521d6..000000000 --- a/test/helpers/latestTime.js +++ /dev/null @@ -1,11 +0,0 @@ -const { ethGetBlock } = require('./web3'); - -// Returns the time of the last mined block in seconds -async function latestTime () { - const block = await ethGetBlock('latest'); - return block.timestamp; -} - -module.exports = { - latestTime, -}; diff --git a/test/helpers/increaseTime.js b/test/helpers/time.js similarity index 78% rename from test/helpers/increaseTime.js rename to test/helpers/time.js index b22ba6b04..b7f3c0001 100644 --- a/test/helpers/increaseTime.js +++ b/test/helpers/time.js @@ -1,7 +1,13 @@ -const { latestTime } = require('./latestTime'); +const { ethGetBlock } = require('./web3'); + +// Returns the time of the last mined block in seconds +async function latest () { + const block = await ethGetBlock('latest'); + return block.timestamp; +} // Increases ganache time by the passed duration in seconds -function increaseTime (duration) { +function increase (duration) { const id = Date.now(); return new Promise((resolve, reject) => { @@ -31,12 +37,12 @@ function increaseTime (duration) { * * @param target time in seconds */ -async function increaseTimeTo (target) { - const now = (await latestTime()); +async function increaseTo (target) { + const now = (await latest()); if (target < now) throw Error(`Cannot increase current time(${now}) to a moment in the past(${target})`); const diff = target - now; - return increaseTime(diff); + return increase(diff); } const duration = { @@ -49,7 +55,8 @@ const duration = { }; module.exports = { - increaseTime, - increaseTimeTo, + latest, + increase, + increaseTo, duration, }; diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index c10b1b821..04441fd1e 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -1,5 +1,4 @@ -const { latestTime } = require('../../helpers/latestTime'); -const { increaseTimeTo, duration } = require('../../helpers/increaseTime'); +const time = require('../../helpers/time'); const { expectThrow } = require('../../helpers/expectThrow'); const BigNumber = web3.BigNumber; @@ -20,7 +19,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('rejects a release time in the past', async function () { - const pastReleaseTime = (await latestTime()) - duration.years(1); + const pastReleaseTime = (await time.latest()) - time.duration.years(1); await expectThrow( TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime) ); @@ -28,7 +27,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { context('once deployed', function () { beforeEach(async function () { - this.releaseTime = (await latestTime()) + duration.years(1); + this.releaseTime = (await time.latest()) + time.duration.years(1); this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime); await this.token.mint(this.timelock.address, amount, { from: minter }); }); @@ -44,24 +43,24 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('cannot be released just before time limit', async function () { - await increaseTimeTo(this.releaseTime - duration.seconds(3)); + await time.increaseTo(this.releaseTime - time.duration.seconds(3)); await expectThrow(this.timelock.release()); }); it('can be released just after limit', async function () { - await increaseTimeTo(this.releaseTime + duration.seconds(1)); + await time.increaseTo(this.releaseTime + time.duration.seconds(1)); await this.timelock.release(); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); it('can be released after time limit', async function () { - await increaseTimeTo(this.releaseTime + duration.years(1)); + await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); it('cannot be released twice', async function () { - await increaseTimeTo(this.releaseTime + duration.years(1)); + await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); await expectThrow(this.timelock.release()); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index 1fe9326f5..7c4fbcc8e 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -1,7 +1,6 @@ const { expectThrow } = require('../../helpers/expectThrow'); const { EVMRevert } = require('../../helpers/EVMRevert'); -const { latestTime } = require('../../helpers/latestTime'); -const { increaseTimeTo, duration } = require('../../helpers/increaseTime'); +const time = require('../../helpers/time'); const { ethGetBlock } = require('../../helpers/web3'); const BigNumber = web3.BigNumber; @@ -18,9 +17,10 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { - this.start = (await latestTime()) + duration.minutes(1); // +1 minute so it starts after contract instantiation - this.cliffDuration = duration.years(1); - this.duration = duration.years(2); + // +1 minute so it starts after contract instantiation + this.start = (await time.latest()) + time.duration.minutes(1); + this.cliffDuration = time.duration.years(1); + this.duration = time.duration.years(2); }); it('rejects a duration shorter than the cliff', async function () { @@ -65,12 +65,12 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('can be released after cliff', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(1)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(1)); await this.vesting.release(this.token.address); }); it('should release proper amount after cliff', async function () { - await increaseTimeTo(this.start + this.cliffDuration); + await time.increaseTo(this.start + this.cliffDuration); const { receipt } = await this.vesting.release(this.token.address); const block = await ethGetBlock(receipt.blockNumber); @@ -87,7 +87,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { for (let i = 1; i <= checkpoints; i++) { const now = this.start + this.cliffDuration + i * (vestingPeriod / checkpoints); - await increaseTimeTo(now); + await time.increaseTo(now); await this.vesting.release(this.token.address); const expectedVesting = amount.mul(now - this.start).div(this.duration).floor(); @@ -97,7 +97,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should have released all after end', async function () { - await increaseTimeTo(this.start + this.duration); + await time.increaseTo(this.start + this.duration); await this.vesting.release(this.token.address); (await this.token.balanceOf(beneficiary)).should.bignumber.equal(amount); (await this.vesting.released(this.token.address)).should.bignumber.equal(amount); @@ -120,7 +120,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should return the non-vested tokens when revoked by owner', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); const vested = await this.vesting.vestedAmount(this.token.address); @@ -130,7 +130,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should keep the vested tokens when revoked by owner', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); const vestedPre = await this.vesting.vestedAmount(this.token.address); @@ -142,7 +142,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should fail to be revoked a second time', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); await this.vesting.vestedAmount(this.token.address); From 269981ee6a02096a20f6997d87e8d43b78906284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 10:37:44 -0300 Subject: [PATCH 028/205] Created test utils directory --- test/{ => utils}/Address.test.js | 0 test/{ => utils}/ReentrancyGuard.test.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/{ => utils}/Address.test.js (100%) rename test/{ => utils}/ReentrancyGuard.test.js (100%) diff --git a/test/Address.test.js b/test/utils/Address.test.js similarity index 100% rename from test/Address.test.js rename to test/utils/Address.test.js diff --git a/test/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js similarity index 100% rename from test/ReentrancyGuard.test.js rename to test/utils/ReentrancyGuard.test.js From f4d6f404424669e0eef7faa05fd89ab9945f265b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 10:48:54 -0300 Subject: [PATCH 029/205] Fixed test path. --- test/utils/ReentrancyGuard.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 7086f8d94..27430652c 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('./helpers/expectThrow'); +const { expectThrow } = require('../helpers/expectThrow'); const ReentrancyMock = artifacts.require('ReentrancyMock'); const ReentrancyAttack = artifacts.require('ReentrancyAttack'); From 43ebb4fc433979d19c4cbec4aa0c25e0e3e9e5f7 Mon Sep 17 00:00:00 2001 From: Anton Bukov Date: Wed, 3 Oct 2018 00:15:59 +0300 Subject: [PATCH 030/205] ERC20 internal transfer method (#1370) --- contracts/token/ERC20/ERC20.sol | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 8fd420a29..3d18c1dec 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -58,12 +58,7 @@ contract ERC20 is IERC20 { * @param value The amount to be transferred. */ function transfer(address to, uint256 value) public returns (bool) { - require(value <= _balances[msg.sender]); - require(to != address(0)); - - _balances[msg.sender] = _balances[msg.sender].sub(value); - _balances[to] = _balances[to].add(value); - emit Transfer(msg.sender, to, value); + _transfer(msg.sender, to, value); return true; } @@ -98,14 +93,10 @@ contract ERC20 is IERC20 { public returns (bool) { - require(value <= _balances[from]); require(value <= _allowed[from][msg.sender]); - require(to != address(0)); - _balances[from] = _balances[from].sub(value); - _balances[to] = _balances[to].add(value); _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); - emit Transfer(from, to, value); + _transfer(from, to, value); return true; } @@ -157,6 +148,21 @@ contract ERC20 is IERC20 { return true; } + /** + * @dev Transfer token for a specified addresses + * @param from The address to transfer from. + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function _transfer(address from, address to, uint256 value) internal { + require(value <= _balances[from]); + require(to != address(0)); + + _balances[from] = _balances[from].sub(value); + _balances[to] = _balances[to].add(value); + emit Transfer(from, to, value); + } + /** * @dev Internal function that mints an amount of the token and assigns it to * an account. This encapsulates the modification of balances such that the From f3888bb0b0a2eba5282a1bd5828135910b65bc8d Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 3 Oct 2018 20:53:08 +0530 Subject: [PATCH 031/205] Removing unrequired `_burn()` override (#1373) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1371 * Removed extra whitespace --- contracts/token/ERC20/ERC20Burnable.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index 014dc7fa8..ba4a2ccbe 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -24,12 +24,4 @@ contract ERC20Burnable is ERC20 { function burnFrom(address from, uint256 value) public { _burnFrom(from, value); } - - /** - * @dev Overrides ERC20._burn in order for burn and burnFrom to emit - * an additional Burn event. - */ - function _burn(address who, uint256 value) internal { - super._burn(who, value); - } } From c87433e0c242f922d37d28710ced32584b561234 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 3 Oct 2018 21:20:01 +0530 Subject: [PATCH 032/205] Prevents Bounty from being claimed twice (#1374) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1356 * Removed extra semicolon. --- contracts/bounties/BreakInvariantBounty.sol | 1 + test/BreakInvariantBounty.test.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/contracts/bounties/BreakInvariantBounty.sol b/contracts/bounties/BreakInvariantBounty.sol index 016d3f2f5..6fd3b6e67 100644 --- a/contracts/bounties/BreakInvariantBounty.sol +++ b/contracts/bounties/BreakInvariantBounty.sol @@ -45,6 +45,7 @@ contract BreakInvariantBounty is PullPayment, Ownable { * @param target contract */ function claim(Target target) public { + require(!_claimed); address researcher = _researchers[target]; require(researcher != address(0)); // Check Target contract invariants diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index ff8e0f7bd..50ae96aaa 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -90,6 +90,10 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar it('no longer accepts rewards', async function () { await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); }); + + it('reverts when reclaimed', async function () { + await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); + }); }); }); }); From 5c228805ad195654c6fb2a3276f1f323d4762666 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 3 Oct 2018 23:13:46 -0300 Subject: [PATCH 033/205] Update issue templates (#1376) * Update issue templates * improve pull request template * remove previous issue template --- .github/ISSUE_TEMPLATE.md | 34 ----------------------- .github/ISSUE_TEMPLATE/bug_report.md | 21 ++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 14 ++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 23 ++++++++------- 4 files changed, 48 insertions(+), 44 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index cafae1e9e..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,34 +0,0 @@ -## 🎉 Description - - - -- [ ] 🐛 This is a bug report. -- [ ] 📈 This is a feature request. - - - -## 💻 Environment - -Next, we need to know what your environment looks like. - -- Which version of OpenZeppelin are you using? -- What network are you deploying to? Ganache? Ropsten? -- How are you deploying your OpenZeppelin-backed contracts? truffle? Remix? Let us know! - -## 📝 Details - -Describe the problem you have been experiencing in more detail. Include as much information as you think is relevant. Keep in mind that transactions can fail for many reasons; context is key here. - -## 🔢 Code To Reproduce Issue [ Good To Have ] - -Please remember that with sample code it's easier to reproduce the bug and it's much faster to fix it. - -``` -insert short code snippets here -``` - - - -## 👍 Other Information - - diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..d932e7632 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,21 @@ +--- +name: Bug report +about: Report a bug in OpenZeppelin + +--- + + + + + +**💻 Environment** + + + +**📝 Details** + + + +**🔢 Code to reproduce bug** + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..404854c00 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request +about: Suggest an idea for OpenZeppelin + +--- + +**🧐 Motivation** + + +**📝 Details** + + + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 72b331668..2d743d0fe 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,17 +1,20 @@ - + + + Fixes # -# 🚀 Description - - + - - -- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md) -- [ ] ✅ I've added tests where applicable to test my new functionality. -- [ ] 📖 I've made sure that my contracts are well-documented. -- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:fix`). + From ace14d3ad73f54c02a1328f939fa2d2afb395882 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 3 Oct 2018 23:17:06 -0300 Subject: [PATCH 034/205] Add note about compiling artifacts to releasing steps (#1377) * add note about compiling artifacts to release notes * add explanation of truffle bug --- RELEASING.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RELEASING.md b/RELEASING.md index 6514b4cf5..40360afcf 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -34,6 +34,12 @@ git push upstream vX.Y.Z-rc.R Draft the release notes in our [GitHub releases](https://github.com/OpenZeppelin/openzeppelin-solidity/releases). Make sure to mark it as a pre-release! Try to be consistent with our previous release notes in the title and format of the text. Release candidates don't need a detailed changelog, but make sure to include a link to GitHub's compare page. +Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. + +1. Delete the `contracts/mocks` and `contracts/examples` directories. +2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) +3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. + Once the CI run for the new tag is green, publish on npm under the `next` tag. ``` @@ -62,6 +68,12 @@ git push upstream vX.Y.Z Draft the release notes in GitHub releases. Try to be consistent with our previous release notes in the title and format of the text. Make sure to include a detailed changelog. +Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. + +1. Delete the `contracts/mocks` and `contracts/examples` directories. +2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) +3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. + Once the CI run for the new tag is green, publish on npm. ``` From fd4de776519e2bd64dc6ac0efb87e0f603c6608f Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 4 Oct 2018 16:21:52 +0530 Subject: [PATCH 035/205] Replaces `amount` with `value` for consistency (#1378) * fixes #1372 * done in ERC20Capped and ERC20Mintable --- contracts/token/ERC20/ERC20.sol | 32 ++++++++++++------------- contracts/token/ERC20/ERC20Capped.sol | 8 +++---- contracts/token/ERC20/ERC20Mintable.sol | 6 ++--- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 3d18c1dec..25b2694a2 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -168,28 +168,28 @@ contract ERC20 is IERC20 { * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. - * @param amount The amount that will be created. + * @param value The amount that will be created. */ - function _mint(address account, uint256 amount) internal { + function _mint(address account, uint256 value) internal { require(account != 0); - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); + _totalSupply = _totalSupply.add(value); + _balances[account] = _balances[account].add(value); + emit Transfer(address(0), account, value); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. - * @param amount The amount that will be burnt. + * @param value The amount that will be burnt. */ - function _burn(address account, uint256 amount) internal { + function _burn(address account, uint256 value) internal { require(account != 0); - require(amount <= _balances[account]); + require(value <= _balances[account]); - _totalSupply = _totalSupply.sub(amount); - _balances[account] = _balances[account].sub(amount); - emit Transfer(account, address(0), amount); + _totalSupply = _totalSupply.sub(value); + _balances[account] = _balances[account].sub(value); + emit Transfer(account, address(0), value); } /** @@ -197,15 +197,15 @@ contract ERC20 is IERC20 { * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * @param account The account whose tokens will be burnt. - * @param amount The amount that will be burnt. + * @param value The amount that will be burnt. */ - function _burnFrom(address account, uint256 amount) internal { - require(amount <= _allowed[account][msg.sender]); + function _burnFrom(address account, uint256 value) internal { + require(value <= _allowed[account][msg.sender]); // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, // this function needs to emit an event with the updated approval. _allowed[account][msg.sender] = _allowed[account][msg.sender].sub( - amount); - _burn(account, amount); + value); + _burn(account, value); } } diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 0a73159b6..9f3ea8bfc 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -27,19 +27,19 @@ contract ERC20Capped is ERC20Mintable { /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. - * @param amount The amount of tokens to mint. + * @param value The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address to, - uint256 amount + uint256 value ) public returns (bool) { - require(totalSupply().add(amount) <= _cap); + require(totalSupply().add(value) <= _cap); - return super.mint(to, amount); + return super.mint(to, value); } } diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index 386abf64d..eb01f06e7 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -11,18 +11,18 @@ contract ERC20Mintable is ERC20, MinterRole { /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. - * @param amount The amount of tokens to mint. + * @param value The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address to, - uint256 amount + uint256 value ) public onlyMinter returns (bool) { - _mint(to, amount); + _mint(to, value); return true; } } From b41b125c15c9ccf8a002a43ed64b5349982c2fb6 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 4 Oct 2018 18:27:37 +0530 Subject: [PATCH 036/205] `this` is used in tests (#1380) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1200 * suggested change --- test/examples/SimpleToken.test.js | 18 ++++++++---------- test/library/MerkleProof.test.js | 10 ++++------ test/token/ERC20/ERC20Detailed.test.js | 10 ++++------ test/utils/ReentrancyGuard.test.js | 13 +++++-------- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index a28cf4641..f59a82000 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -8,34 +8,32 @@ require('chai') .should(); contract('SimpleToken', function ([_, creator]) { - let token; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { - token = await SimpleToken.new({ from: creator }); + this.token = await SimpleToken.new({ from: creator }); }); it('has a name', async function () { - (await token.name()).should.equal('SimpleToken'); + (await this.token.name()).should.equal('SimpleToken'); }); it('has a symbol', async function () { - (await token.symbol()).should.equal('SIM'); + (await this.token.symbol()).should.equal('SIM'); }); it('has 18 decimals', async function () { - (await token.decimals()).should.be.bignumber.equal(18); + (await this.token.decimals()).should.be.bignumber.equal(18); }); it('assigns the initial total supply to the creator', async function () { - const totalSupply = await token.totalSupply(); - const creatorBalance = await token.balanceOf(creator); + const totalSupply = await this.token.totalSupply(); + const creatorBalance = await this.token.balanceOf(creator); creatorBalance.should.be.bignumber.equal(totalSupply); - const receipt = await web3.eth.getTransactionReceipt(token.transactionHash); - const logs = decodeLogs(receipt.logs, SimpleToken, token.address); + const receipt = await web3.eth.getTransactionReceipt(this.token.transactionHash); + const logs = decodeLogs(receipt.logs, SimpleToken, this.token.address); logs.length.should.equal(1); logs[0].event.should.equal('Transfer'); logs[0].args.from.valueOf().should.equal(ZERO_ADDRESS); diff --git a/test/library/MerkleProof.test.js b/test/library/MerkleProof.test.js index 6674880b7..b5d8fbe07 100644 --- a/test/library/MerkleProof.test.js +++ b/test/library/MerkleProof.test.js @@ -7,10 +7,8 @@ require('chai') .should(); contract('MerkleProof', function () { - let merkleProof; - beforeEach(async function () { - merkleProof = await MerkleProofWrapper.new(); + this.merkleProof = await MerkleProofWrapper.new(); }); describe('verify', function () { @@ -24,7 +22,7 @@ contract('MerkleProof', function () { const leaf = bufferToHex(sha3(elements[0])); - (await merkleProof.verify(proof, root, leaf)).should.equal(true); + (await this.merkleProof.verify(proof, root, leaf)).should.equal(true); }); it('should return false for an invalid Merkle proof', async function () { @@ -40,7 +38,7 @@ contract('MerkleProof', function () { const badProof = badMerkleTree.getHexProof(badElements[0]); - (await merkleProof.verify(badProof, correctRoot, correctLeaf)).should.equal(false); + (await this.merkleProof.verify(badProof, correctRoot, correctLeaf)).should.equal(false); }); it('should return false for a Merkle proof of invalid length', async function () { @@ -54,7 +52,7 @@ contract('MerkleProof', function () { const leaf = bufferToHex(sha3(elements[0])); - (await merkleProof.verify(badProof, root, leaf)).should.equal(false); + (await this.merkleProof.verify(badProof, root, leaf)).should.equal(false); }); }); }); diff --git a/test/token/ERC20/ERC20Detailed.test.js b/test/token/ERC20/ERC20Detailed.test.js index 71b22a7b9..7965b7e9d 100644 --- a/test/token/ERC20/ERC20Detailed.test.js +++ b/test/token/ERC20/ERC20Detailed.test.js @@ -7,25 +7,23 @@ require('chai') const ERC20DetailedMock = artifacts.require('ERC20DetailedMock'); contract('ERC20Detailed', function () { - let detailedERC20 = null; - const _name = 'My Detailed ERC20'; const _symbol = 'MDT'; const _decimals = 18; beforeEach(async function () { - detailedERC20 = await ERC20DetailedMock.new(_name, _symbol, _decimals); + this.detailedERC20 = await ERC20DetailedMock.new(_name, _symbol, _decimals); }); it('has a name', async function () { - (await detailedERC20.name()).should.be.equal(_name); + (await this.detailedERC20.name()).should.be.equal(_name); }); it('has a symbol', async function () { - (await detailedERC20.symbol()).should.be.equal(_symbol); + (await this.detailedERC20.symbol()).should.be.equal(_symbol); }); it('has an amount of decimals', async function () { - (await detailedERC20.decimals()).should.be.bignumber.equal(_decimals); + (await this.detailedERC20.decimals()).should.be.bignumber.equal(_decimals); }); }); diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 27430652c..3952b2fcb 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -9,17 +9,14 @@ require('chai') .should(); contract('ReentrancyGuard', function () { - let reentrancyMock; - beforeEach(async function () { - reentrancyMock = await ReentrancyMock.new(); - const initialCounter = await reentrancyMock.counter(); - initialCounter.should.be.bignumber.equal(0); + this.reentrancyMock = await ReentrancyMock.new(); + (await this.reentrancyMock.counter()).should.be.bignumber.equal(0); }); it('should not allow remote callback', async function () { const attacker = await ReentrancyAttack.new(); - await expectThrow(reentrancyMock.countAndCall(attacker.address)); + await expectThrow(this.reentrancyMock.countAndCall(attacker.address)); }); // The following are more side-effects than intended behavior: @@ -27,10 +24,10 @@ contract('ReentrancyGuard', function () { // in the side-effects. it('should not allow local recursion', async function () { - await expectThrow(reentrancyMock.countLocalRecursive(10)); + await expectThrow(this.reentrancyMock.countLocalRecursive(10)); }); it('should not allow indirect local recursion', async function () { - await expectThrow(reentrancyMock.countThisRecursive(10)); + await expectThrow(this.reentrancyMock.countThisRecursive(10)); }); }); From 744f567f40bcd31f821a35d2a9a004602e28a1e9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 4 Oct 2018 11:10:08 -0300 Subject: [PATCH 037/205] Separate ERC721Mintable (#1365) * separate part of ERC721Mintable into ERC721MetadataMintable * remove mint and burn from 721 tests * Fixed linter error. * fix ERC721 mint tests * Minor fixes. --- contracts/mocks/ERC721FullMock.sol | 7 ++-- .../mocks/ERC721MintableBurnableImpl.sol | 3 +- .../token/ERC721/ERC721MetadataMintable.sol | 32 +++++++++++++++++++ contracts/token/ERC721/ERC721Mintable.sol | 18 ++--------- test/token/ERC721/ERC721Full.test.js | 2 -- test/token/ERC721/ERC721MintBurn.behavior.js | 4 +-- 6 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 contracts/token/ERC721/ERC721MetadataMintable.sol diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index d555b1f83..2d85e7372 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -2,14 +2,17 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; +import "../token/ERC721/ERC721MetadataMintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; /** - * @title ERC721Mock + * @title ERC721FullMock * This mock just provides a public mint and burn functions for testing purposes, * and a public setter for metadata URI */ -contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721Burnable { +contract ERC721FullMock + is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { + constructor(string name, string symbol) public ERC721Mintable() ERC721Full(name, symbol) diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index 03ff3ac37..51d3ff4f6 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -2,13 +2,14 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; +import "../token/ERC721/ERC721MetadataMintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; /** * @title ERC721MintableBurnableImpl */ contract ERC721MintableBurnableImpl - is ERC721Full, ERC721Mintable, ERC721Burnable { + is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { constructor() ERC721Mintable() diff --git a/contracts/token/ERC721/ERC721MetadataMintable.sol b/contracts/token/ERC721/ERC721MetadataMintable.sol new file mode 100644 index 000000000..95a9f2124 --- /dev/null +++ b/contracts/token/ERC721/ERC721MetadataMintable.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "./ERC721Metadata.sol"; +import "../../access/roles/MinterRole.sol"; + + +/** + * @title ERC721MetadataMintable + * @dev ERC721 minting logic with metadata + */ +contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { + /** + * @dev Function to mint tokens + * @param to The address that will receive the minted tokens. + * @param tokenId The token id to mint. + * @param tokenURI The token URI of the minted token. + * @return A boolean that indicates if the operation was successful. + */ + function mintWithTokenURI( + address to, + uint256 tokenId, + string tokenURI + ) + public + onlyMinter + returns (bool) + { + _mint(to, tokenId); + _setTokenURI(tokenId, tokenURI); + return true; + } +} diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index 9dc0ad751..74b7b0186 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -1,13 +1,13 @@ pragma solidity ^0.4.24; -import "./ERC721Full.sol"; +import "./ERC721.sol"; import "../../access/roles/MinterRole.sol"; /** * @title ERC721Mintable * @dev ERC721 minting logic */ -contract ERC721Mintable is ERC721Full, MinterRole { +contract ERC721Mintable is ERC721, MinterRole { /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. @@ -25,18 +25,4 @@ contract ERC721Mintable is ERC721Full, MinterRole { _mint(to, tokenId); return true; } - - function mintWithTokenURI( - address to, - uint256 tokenId, - string tokenURI - ) - public - onlyMinter - returns (bool) - { - mint(to, tokenId); - _setTokenURI(tokenId, tokenURI); - return true; - } } diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index f4666d0d9..30e4547c8 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -1,6 +1,5 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); -const { shouldBehaveLikeMintAndBurnERC721 } = require('./ERC721MintBurn.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const BigNumber = web3.BigNumber; @@ -221,7 +220,6 @@ contract('ERC721Full', function ([ }); shouldBehaveLikeERC721(creator, minter, accounts); - shouldBehaveLikeMintAndBurnERC721(creator, minter, accounts); shouldSupportInterfaces([ 'ERC165', diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index 8aeccd5d8..bcf7e9ed3 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -52,13 +52,13 @@ function shouldBehaveLikeMintAndBurnERC721 ( describe('when the given owner address is the zero address', function () { it('reverts', async function () { - await assertRevert(this.token.mint(ZERO_ADDRESS, thirdTokenId)); + await assertRevert(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); }); }); describe('when the given token ID was already tracked by this contract', function () { it('reverts', async function () { - await assertRevert(this.token.mint(owner, firstTokenId)); + await assertRevert(this.token.mint(owner, firstTokenId, { from: minter })); }); }); }); From 308e5e9cc0bc9a65436cf3ae933551e1a62167ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 4 Oct 2018 11:15:22 -0300 Subject: [PATCH 038/205] Removed unnecessary Secondary inheritance from RefundEscrow. (#1381) --- contracts/payment/RefundEscrow.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/RefundEscrow.sol index 3eca6bbcf..c3770dbbb 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/RefundEscrow.sol @@ -1,7 +1,6 @@ pragma solidity ^0.4.24; import "./ConditionalEscrow.sol"; -import "../ownership/Secondary.sol"; /** * @title RefundEscrow @@ -9,7 +8,7 @@ import "../ownership/Secondary.sol"; * The primary account may close the deposit period, and allow for either withdrawal * by the beneficiary, or refunds to the depositors. */ -contract RefundEscrow is Secondary, ConditionalEscrow { +contract RefundEscrow is ConditionalEscrow { enum State { Active, Refunding, Closed } event Closed(); From b17de011dc336ed329d70fb0c7950b67b8192292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 5 Oct 2018 22:18:59 -0300 Subject: [PATCH 039/205] Removed old, unused mocks. (#1382) --- contracts/mocks/ForceEther.sol | 15 ---------- contracts/mocks/MessageHelper.sol | 49 ------------------------------- 2 files changed, 64 deletions(-) delete mode 100644 contracts/mocks/ForceEther.sol delete mode 100644 contracts/mocks/MessageHelper.sol diff --git a/contracts/mocks/ForceEther.sol b/contracts/mocks/ForceEther.sol deleted file mode 100644 index bca5646f3..000000000 --- a/contracts/mocks/ForceEther.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.24; - -// @title Force Ether into a contract. -// @notice even -// if the contract is not payable. -// @notice To use, construct the contract with the target as argument. -// @author Remco Bloemen -contract ForceEther { - - constructor() public payable { } - - function destroyAndSend(address recipient) public { - selfdestruct(recipient); - } -} diff --git a/contracts/mocks/MessageHelper.sol b/contracts/mocks/MessageHelper.sol deleted file mode 100644 index 54c084414..000000000 --- a/contracts/mocks/MessageHelper.sol +++ /dev/null @@ -1,49 +0,0 @@ -pragma solidity ^0.4.24; - -contract MessageHelper { - - event Show(bytes32 b32, uint256 number, string text); - event Buy(bytes32 b32, uint256 number, string text, uint256 value); - - function showMessage( - bytes32 _message, - uint256 _number, - string _text - ) - public - returns (bool) - { - emit Show(_message, _number, _text); - return true; - } - - function buyMessage( - bytes32 _message, - uint256 _number, - string _text - ) - public - payable - returns (bool) - { - emit Buy( - _message, - _number, - _text, - msg.value); - return true; - } - - function fail() public { - require(false); - } - - function call(address _to, bytes _data) public returns (bool) { - // solium-disable-next-line security/no-low-level-calls - if (_to.call(_data)) - return true; - else - return false; - } - -} From 41f84f8b402efcda35f84ea9d7ffca4bb5f86499 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 8 Oct 2018 19:21:06 +0530 Subject: [PATCH 040/205] Removed selfdestruct from BreakInvariantBounty (#1385) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1384 * introduced claimable and cancelBounty * cancelBounty tests * Update BreakInvariantBounty.test.js --- contracts/bounties/BreakInvariantBounty.sol | 26 +++++---- test/BreakInvariantBounty.test.js | 63 ++++++++++++++------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/contracts/bounties/BreakInvariantBounty.sol b/contracts/bounties/BreakInvariantBounty.sol index 6fd3b6e67..52077a539 100644 --- a/contracts/bounties/BreakInvariantBounty.sol +++ b/contracts/bounties/BreakInvariantBounty.sol @@ -8,24 +8,25 @@ import "../ownership/Ownable.sol"; * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. */ contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimed; + bool private _claimable = true; mapping(address => address) private _researchers; event TargetCreated(address createdAddress); + event BountyCanceled(); /** * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. */ function() external payable { - require(!_claimed); + require(_claimable); } /** - * @dev Determine if the bounty was claimed. - * @return true if the bounty was claimed, false otherwise. + * @dev Determine if the bounty is claimable. + * @return false if the bounty was claimed, true otherwise. */ - function claimed() public view returns(bool) { - return _claimed; + function claimable() public view returns(bool) { + return _claimable; } /** @@ -45,20 +46,23 @@ contract BreakInvariantBounty is PullPayment, Ownable { * @param target contract */ function claim(Target target) public { - require(!_claimed); + require(_claimable); address researcher = _researchers[target]; require(researcher != address(0)); // Check Target contract invariants require(!target.checkInvariant()); _asyncTransfer(researcher, address(this).balance); - _claimed = true; + _claimable = false; } /** - * @dev Transfers the current balance to the owner and terminates the contract. + * @dev Cancels the bounty and transfers all funds to the owner */ - function destroy() public onlyOwner { - selfdestruct(owner()); + function cancelBounty() public onlyOwner{ + require(_claimable); + _asyncTransfer(owner(), address(this).balance); + _claimable = false; + emit BountyCanceled(); } /** diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index 50ae96aaa..5995f64f5 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -1,4 +1,5 @@ const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); +const { ether } = require('./helpers/ether'); const { sendEther } = require('./helpers/sendTransaction'); const { balanceDifference } = require('./helpers/balanceDiff'); const expectEvent = require('./helpers/expectEvent'); @@ -11,7 +12,7 @@ require('chai') .use(require('chai-bignumber')(web3.BigNumber)) .should(); -const reward = new web3.BigNumber(web3.toWei(1, 'ether')); +const reward = ether(1); contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTarget]) { beforeEach(async function () { @@ -28,24 +29,9 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar await sendEther(owner, this.bounty.address, reward); }); - describe('destroy', function () { - it('returns all balance to the owner', async function () { - const ownerPreBalance = await ethGetBalance(owner); - await this.bounty.destroy({ from: owner, gasPrice: 0 }); - const ownerPostBalance = await ethGetBalance(owner); - - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); - ownerPostBalance.sub(ownerPreBalance).should.be.bignumber.equal(reward); - }); - - it('reverts when called by anyone', async function () { - await assertRevert(this.bounty.destroy({ from: anyone })); - }); - }); - describe('claim', function () { - it('is initially unclaimed', async function () { - (await this.bounty.claimed()).should.equal(false); + it('is initially claimable', async function () { + (await this.bounty.claimable()).should.equal(true); }); it('can create claimable target', async function () { @@ -83,8 +69,8 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar await this.bounty.claim(this.target.address, { from: researcher }); }); - it('is claimed', async function () { - (await this.bounty.claimed()).should.equal(true); + it('is not claimable', async function () { + (await this.bounty.claimable()).should.equal(false); }); it('no longer accepts rewards', async function () { @@ -104,5 +90,42 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); }); }); + + describe('cancelBounty', function () { + context('before canceling', function () { + it('is claimable', async function () { + (await this.bounty.claimable()).should.equal(true); + }); + + it('can be canceled by the owner', async function () { + const { logs } = await this.bounty.cancelBounty({ from: owner }); + expectEvent.inLogs(logs, 'BountyCanceled'); + (await balanceDifference(owner, () => this.bounty.withdrawPayments(owner))) + .should.be.bignumber.equal(reward); + }); + + it('reverts when canceled by anyone', async function () { + await assertRevert(this.bounty.cancelBounty({ from: anyone })); + }); + }); + + context('after canceling', async function () { + beforeEach(async function () { + await this.bounty.cancelBounty({ from: owner }); + }); + + it('is not claimable', async function () { + (await this.bounty.claimable()).should.equal(false); + }); + + it('no longer accepts rewards', async function () { + await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); + }); + + it('reverts when recanceled', async function () { + await assertRevert(this.bounty.cancelBounty({ from: owner })); + }); + }); + }); }); }); From f7e53d90fa638553ffc93e93fe1b12fc081bb774 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Mon, 8 Oct 2018 16:01:33 +0200 Subject: [PATCH 041/205] Add Arrays library with unit tests (#1209) (#1375) * Add Arrays library with unit tests (#1209) * prepared due to snapshot token requirements * add library with method to find upper bound * add unit test for basic and edge cases * Imporove documentation for Arrays library Simplify Arrays.test.js to use short arrays as test date * Added comment for uint256 mid variable. * Explaned why uint256 mid variable calculated as Math.average is safe to use as index of array. --- contracts/mocks/ArraysImpl.sol | 18 +++++++ contracts/utils/Arrays.sol | 56 ++++++++++++++++++++++ test/utils/Arrays.test.js | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 contracts/mocks/ArraysImpl.sol create mode 100644 contracts/utils/Arrays.sol create mode 100644 test/utils/Arrays.test.js diff --git a/contracts/mocks/ArraysImpl.sol b/contracts/mocks/ArraysImpl.sol new file mode 100644 index 000000000..8a2b9ec51 --- /dev/null +++ b/contracts/mocks/ArraysImpl.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + +import "../utils/Arrays.sol"; + +contract ArraysImpl { + + using Arrays for uint256[]; + + uint256[] private array; + + constructor(uint256[] _array) public { + array = _array; + } + + function findUpperBound(uint256 _element) external view returns (uint256) { + return array.findUpperBound(_element); + } +} diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol new file mode 100644 index 000000000..6882ea995 --- /dev/null +++ b/contracts/utils/Arrays.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.23; + +import "../math/Math.sol"; + + +/** + * @title Arrays + * @dev Utility library of inline array functions + */ +library Arrays { + + /** + * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted + * array to find index of the element value. If element is found then returns it's index otherwise + * it returns index of first element which is grater than searched value. If searched element is + * bigger than any array element function then returns first index after last element (i.e. all + * values inside the array are smaller than the target). Complexity O(log n). + * @param array The array sorted in ascending order. + * @param element The element's value to be find. + * @return The calculated index value. Returns 0 for empty array. + */ + function findUpperBound( + uint256[] storage array, + uint256 element + ) + internal + view + returns (uint256) + { + if (array.length == 0) { + return 0; + } + + uint256 low = 0; + uint256 high = array.length; + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds down (it does integer division with truncation). + if (array[mid] > element) { + high = mid; + } else { + low = mid + 1; + } + } + + // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. + if (low > 0 && array[low - 1] == element) { + return low - 1; + } else { + return low; + } + } +} diff --git a/test/utils/Arrays.test.js b/test/utils/Arrays.test.js new file mode 100644 index 000000000..4bfc9eaba --- /dev/null +++ b/test/utils/Arrays.test.js @@ -0,0 +1,87 @@ +const ArraysImpl = artifacts.require('ArraysImpl'); + +const BigNumber = web3.BigNumber; + +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +contract('Arrays', function () { + context('Even number of elements', function () { + const EVEN_ELEMENTS_ARRAY = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(EVEN_ELEMENTS_ARRAY); + }); + + it('should return correct index for the basic case', async function () { + (await this.arrays.findUpperBound(16)).should.be.bignumber.equal(5); + }); + + it('should return 0 for the first element', async function () { + (await this.arrays.findUpperBound(11)).should.be.bignumber.equal(0); + }); + + it('should return index of the last element', async function () { + (await this.arrays.findUpperBound(20)).should.be.bignumber.equal(9); + }); + + it('should return first index after last element if searched value is over the upper boundary', async function () { + (await this.arrays.findUpperBound(32)).should.be.bignumber.equal(10); + }); + + it('should return 0 for the element under the lower boundary', async function () { + (await this.arrays.findUpperBound(2)).should.be.bignumber.equal(0); + }); + }); + + context('Odd number of elements', function () { + const ODD_ELEMENTS_ARRAY = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(ODD_ELEMENTS_ARRAY); + }); + + it('should return correct index for the basic case', async function () { + (await this.arrays.findUpperBound(16)).should.be.bignumber.equal(5); + }); + + it('should return 0 for the first element', async function () { + (await this.arrays.findUpperBound(11)).should.be.bignumber.equal(0); + }); + + it('should return index of the last element', async function () { + (await this.arrays.findUpperBound(21)).should.be.bignumber.equal(10); + }); + + it('should return first index after last element if searched value is over the upper boundary', async function () { + (await this.arrays.findUpperBound(32)).should.be.bignumber.equal(11); + }); + + it('should return 0 for the element under the lower boundary', async function () { + (await this.arrays.findUpperBound(2)).should.be.bignumber.equal(0); + }); + }); + + context('Array with gap', function () { + const WITH_GAP_ARRAY = [11, 12, 13, 14, 15, 20, 21, 22, 23, 24]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(WITH_GAP_ARRAY); + }); + + it('should return index of first element in next filled range', async function () { + (await this.arrays.findUpperBound(17)).should.be.bignumber.equal(5); + }); + }); + + context('Empty array', function () { + beforeEach(async function () { + this.arrays = await ArraysImpl.new([]); + }); + + it('should always return 0 for empty array', async function () { + (await this.arrays.findUpperBound(10)).should.be.bignumber.equal(0); + }); + }); +}); From 3acc2b4216394d4d66b717f40891e64a99aed8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 8 Oct 2018 20:01:35 -0300 Subject: [PATCH 042/205] Added a constructor to BreakInvariantBounty. (#1395) --- contracts/bounties/BreakInvariantBounty.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/bounties/BreakInvariantBounty.sol b/contracts/bounties/BreakInvariantBounty.sol index 52077a539..6dec45a3b 100644 --- a/contracts/bounties/BreakInvariantBounty.sol +++ b/contracts/bounties/BreakInvariantBounty.sol @@ -8,12 +8,16 @@ import "../ownership/Ownable.sol"; * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. */ contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimable = true; + bool private _claimable; mapping(address => address) private _researchers; event TargetCreated(address createdAddress); event BountyCanceled(); + constructor() public { + _claimable = true; + } + /** * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. */ From af42c39e6cb835b220c2ce8ef6247f074707baf7 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Tue, 9 Oct 2018 22:02:45 +0530 Subject: [PATCH 043/205] Improves Ownable events (#1397) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1392 * event tests added * constructor event added --- contracts/ownership/Ownable.sol | 4 ++-- test/ownership/Ownable.behavior.js | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index d8ede5cd2..5279d5d42 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -8,7 +8,6 @@ pragma solidity ^0.4.24; contract Ownable { address private _owner; - event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner @@ -20,6 +19,7 @@ contract Ownable { */ constructor() public { _owner = msg.sender; + emit OwnershipTransferred(address(0), _owner); } /** @@ -51,7 +51,7 @@ contract Ownable { * modifier anymore. */ function renounceOwnership() public onlyOwner { - emit OwnershipRenounced(_owner); + emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index eac3c10ce..baf609c57 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,5 +1,6 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); +const expectEvent = require('../helpers/expectEvent'); const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; @@ -14,7 +15,8 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { it('changes owner after transfer', async function () { (await this.ownable.isOwner({ from: anyone })).should.be.equal(false); - await this.ownable.transferOwnership(anyone, { from: owner }); + const { logs } = await this.ownable.transferOwnership(anyone, { from: owner }); + expectEvent.inLogs(logs, 'OwnershipTransferred'); (await this.ownable.owner()).should.equal(anyone); (await this.ownable.isOwner({ from: anyone })).should.be.equal(true); @@ -29,7 +31,9 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('loses owner after renouncement', async function () { - await this.ownable.renounceOwnership({ from: owner }); + const { logs } = await this.ownable.renounceOwnership({ from: owner }); + expectEvent.inLogs(logs, 'OwnershipTransferred'); + (await this.ownable.owner()).should.equal(ZERO_ADDRESS); }); From 58a42443dfe57a2c0e161539d0b363e5ca7bf8d9 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 10 Oct 2018 00:16:09 +0530 Subject: [PATCH 044/205] added a test helper with common constants (#1400) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1206 --- test/access/Roles.test.js | 4 +--- test/access/roles/PublicRole.behavior.js | 2 +- test/crowdsale/AllowanceCrowdsale.test.js | 2 +- test/crowdsale/Crowdsale.test.js | 2 +- test/drafts/ERC20Migrator.test.js | 4 +--- test/examples/SimpleToken.test.js | 3 +-- test/helpers/constants.js | 6 ++++++ test/math/SafeMath.test.js | 7 +++---- test/ownership/Ownable.behavior.js | 3 +-- test/ownership/Secondary.test.js | 4 +--- test/payment/ConditionalEscrow.test.js | 3 ++- test/payment/Escrow.behavior.js | 3 ++- test/payment/PullPayment.test.js | 3 ++- test/payment/RefundEscrow.test.js | 5 +++-- test/payment/SplitPayment.test.js | 5 +++-- test/token/ERC20/ERC20.test.js | 3 +-- test/token/ERC20/TokenVesting.test.js | 2 +- test/token/ERC20/behaviors/ERC20Burnable.behavior.js | 2 +- test/token/ERC20/behaviors/ERC20Mintable.behavior.js | 3 +-- test/token/ERC721/ERC721.behavior.js | 2 +- test/token/ERC721/ERC721MintBurn.behavior.js | 2 +- test/token/ERC721/ERC721PausedToken.behavior.js | 2 +- 22 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 test/helpers/constants.js diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 7d5573cec..76517492c 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -1,13 +1,11 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const RolesMock = artifacts.require('RolesMock'); require('chai') .should(); contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.roles = await RolesMock.new(); }); diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index f1c723b78..a3067f88e 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -1,4 +1,5 @@ const { assertRevert } = require('../../helpers/assertRevert'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const expectEvent = require('../../helpers/expectEvent'); require('chai') @@ -10,7 +11,6 @@ function capitalize (str) { function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename) { rolename = capitalize(rolename); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; describe('should behave like public role', function () { beforeEach('check preconditions', async function () { diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index c0ff4cd91..c6f825126 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -2,6 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -17,7 +18,6 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW const value = ether(0.42); const expectedTokenAmount = rate.mul(value); const tokenAllowance = new BigNumber('1e22'); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { this.token = await SimpleToken.new({ from: tokenWallet }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 4113f7cb4..b1f3b381f 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -2,6 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const { assertRevert } = require('../helpers/assertRevert'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -17,7 +18,6 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { const value = ether(42); const tokenSupply = new BigNumber('1e22'); const expectedTokenAmount = rate.mul(value); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; it('requires a non-null token', async function () { await assertRevert( diff --git a/test/drafts/ERC20Migrator.test.js b/test/drafts/ERC20Migrator.test.js index 315a7ea78..608dce860 100644 --- a/test/drafts/ERC20Migrator.test.js +++ b/test/drafts/ERC20Migrator.test.js @@ -1,5 +1,5 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const ERC20Mock = artifacts.require('ERC20Mock'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20Migrator = artifacts.require('ERC20Migrator'); @@ -11,8 +11,6 @@ require('chai') .should(); contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - const totalSupply = 200; it('reverts with a null legacy token address', async function () { diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index f59a82000..e7f8fa5c1 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -1,4 +1,5 @@ const { decodeLogs } = require('../helpers/decodeLogs'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const SimpleToken = artifacts.require('SimpleToken'); const BigNumber = web3.BigNumber; @@ -8,8 +9,6 @@ require('chai') .should(); contract('SimpleToken', function ([_, creator]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.token = await SimpleToken.new({ from: creator }); }); diff --git a/test/helpers/constants.js b/test/helpers/constants.js new file mode 100644 index 000000000..70d2242a3 --- /dev/null +++ b/test/helpers/constants.js @@ -0,0 +1,6 @@ +const BigNumber = web3.BigNumber; + +module.exports = { + ZERO_ADDRESS: '0x0000000000000000000000000000000000000000', + MAX_UINT256: new BigNumber(2).pow(256).minus(1), +}; diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index 0174bd0ac..56cedeb84 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,4 +1,5 @@ const { assertRevert } = require('../helpers/assertRevert'); +const { MAX_UINT256 } = require('../helpers/constants'); const BigNumber = web3.BigNumber; const SafeMathMock = artifacts.require('SafeMathMock'); @@ -8,8 +9,6 @@ require('chai') .should(); contract('SafeMath', function () { - const MAX_UINT = new BigNumber(2).pow(256).minus(1); - beforeEach(async function () { this.safeMath = await SafeMathMock.new(); }); @@ -23,7 +22,7 @@ contract('SafeMath', function () { }); it('throws a revert error on addition overflow', async function () { - const a = MAX_UINT; + const a = MAX_UINT256; const b = new BigNumber(1); await assertRevert(this.safeMath.add(a, b)); @@ -62,7 +61,7 @@ contract('SafeMath', function () { }); it('throws a revert error on multiplication overflow', async function () { - const a = MAX_UINT; + const a = MAX_UINT256; const b = new BigNumber(2); await assertRevert(this.safeMath.mul(a, b)); diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index baf609c57..1e2fd7564 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,8 +1,7 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const expectEvent = require('../helpers/expectEvent'); - -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; +const { ZERO_ADDRESS } = require('../helpers/constants'); require('chai') .should(); diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 000d0af11..31676be79 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,13 +1,11 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const SecondaryMock = artifacts.require('SecondaryMock'); require('chai') .should(); contract('Secondary', function ([_, primary, newPrimary, anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.secondary = await SecondaryMock.new({ from: primary }); }); diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/ConditionalEscrow.test.js index 5115fee48..03eed68f7 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/ConditionalEscrow.test.js @@ -1,6 +1,7 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -24,7 +25,7 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) { }); context('when withdrawal is disallowed', function () { - const amount = web3.toWei(23.0, 'ether'); + const amount = ether(23.0); beforeEach(async function () { await this.escrow.setAllowed(payee, false); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 57f1fe5d0..9769291e1 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -2,6 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -10,7 +11,7 @@ require('chai') .should(); function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { - const amount = web3.toWei(42.0, 'ether'); + const amount = ether(42.0); describe('as an escrow', function () { describe('deposits', function () { diff --git a/test/payment/PullPayment.test.js b/test/payment/PullPayment.test.js index 1eab3911f..1f4bcc525 100644 --- a/test/payment/PullPayment.test.js +++ b/test/payment/PullPayment.test.js @@ -1,4 +1,5 @@ const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -9,7 +10,7 @@ require('chai') const PullPaymentMock = artifacts.require('PullPaymentMock'); contract('PullPayment', function ([_, payer, payee1, payee2]) { - const amount = web3.toWei(17.0, 'ether'); + const amount = ether(17.0); beforeEach(async function () { this.contract = await PullPaymentMock.new({ value: amount }); diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index c499f4009..a3d669d69 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -2,6 +2,8 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -12,9 +14,8 @@ require('chai') const RefundEscrow = artifacts.require('RefundEscrow'); contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee2]) { - const amount = web3.toWei(54.0, 'ether'); + const amount = ether(54.0); const refundees = [refundee1, refundee2]; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; it('requires a non-null beneficiary', async function () { await expectThrow( diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index cf9ef0e01..c4a720fb9 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -1,5 +1,7 @@ const { ethGetBalance } = require('../helpers/web3'); const { sendEther } = require('./../helpers/sendTransaction'); +const { ether } = require('../helpers/ether'); +const { ZERO_ADDRESS } = require('./../helpers/constants'); const BigNumber = web3.BigNumber; @@ -12,8 +14,7 @@ const { EVMRevert } = require('../helpers/EVMRevert.js'); const SplitPayment = artifacts.require('SplitPayment'); contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { - const amount = web3.toWei(1.0, 'ether'); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + const amount = ether(1.0); it('rejects an empty set of payees', async function () { await expectThrow(SplitPayment.new([], []), EVMRevert); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index e991c2ae6..e224de942 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const ERC20Mock = artifacts.require('ERC20Mock'); @@ -10,8 +11,6 @@ require('chai') .should(); contract('ERC20', function ([_, owner, recipient, anotherAccount]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.token = await ERC20Mock.new(owner, 100); }); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index 7c4fbcc8e..acfdb9adc 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -2,6 +2,7 @@ const { expectThrow } = require('../../helpers/expectThrow'); const { EVMRevert } = require('../../helpers/EVMRevert'); const time = require('../../helpers/time'); const { ethGetBlock } = require('../../helpers/web3'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -14,7 +15,6 @@ const TokenVesting = artifacts.require('TokenVesting'); contract('TokenVesting', function ([_, owner, beneficiary]) { const amount = new BigNumber(1000); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { // +1 minute so it starts after contract instantiation diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index c52594d18..25af3254c 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -1,8 +1,8 @@ const { assertRevert } = require('../../../helpers/assertRevert'); const expectEvent = require('../../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../../helpers/constants'); const BigNumber = web3.BigNumber; -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; require('chai') .use(require('chai-bignumber')(BigNumber)) diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index dbda9eeed..f34504afc 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../../helpers/assertRevert'); const expectEvent = require('../../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -8,8 +9,6 @@ require('chai') .should(); function shouldBehaveLikeERC20Mintable (minter, [anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - describe('as a mintable token', function () { describe('mint', function () { const amount = 100; diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index ce56747de..a18b6b437 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,6 +1,7 @@ const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const { assertRevert } = require('../../helpers/assertRevert'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); @@ -19,7 +20,6 @@ function shouldBehaveLikeERC721 ( const firstTokenId = 1; const secondTokenId = 2; const unknownTokenId = 3; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const RECEIVER_MAGIC_VALUE = '0x150b7a02'; describe('like an ERC721', function () { diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index bcf7e9ed3..a5141abca 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; require('chai') @@ -15,7 +16,6 @@ function shouldBehaveLikeMintAndBurnERC721 ( const secondTokenId = 2; const thirdTokenId = 3; const unknownTokenId = 4; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const MOCK_URI = 'https://example.com'; describe('like a mintable and burnable ERC721', function () { diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index d14e6a395..a7196d837 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { sendTransaction } = require('../../helpers/sendTransaction'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -11,7 +12,6 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { const firstTokenId = 1; const mintedTokens = 1; const mockData = '0x42'; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; describe('like a paused ERC721', function () { beforeEach(async function () { From b0da0fded0adcaf1f5ae9c4d62d39ac05763afea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 9 Oct 2018 16:23:55 -0300 Subject: [PATCH 045/205] Replaced assertJump, assertRevert and expectThrow with shouldFail. (#1363) * Replaced assertJump, assertRevert and expectThrow with shouldFail. * Fixed linter errors. * Fixed typo. * Made the helpers async. --- test/BreakInvariantBounty.test.js | 16 ++++---- test/access/Roles.test.js | 9 +++-- test/access/roles/PublicRole.behavior.js | 10 ++--- test/crowdsale/AllowanceCrowdsale.test.js | 4 +- test/crowdsale/CappedCrowdsale.test.js | 18 ++------- test/crowdsale/Crowdsale.test.js | 14 +++---- test/crowdsale/FinalizableCrowdsale.test.js | 7 ++-- .../IncreasingPriceCrowdsale.test.js | 6 +-- .../IndividuallyCappedCrowdsale.test.js | 15 ++++---- test/crowdsale/MintedCrowdsale.test.js | 6 +-- test/crowdsale/PostDeliveryCrowdsale.test.js | 7 ++-- test/crowdsale/RefundableCrowdsale.test.js | 16 +++----- test/crowdsale/TimedCrowdsale.test.js | 19 +++++----- test/drafts/ERC20Migrator.test.js | 13 ++++--- test/drafts/SignatureBouncer.test.js | 26 ++++++------- test/examples/SampleCrowdsale.test.js | 22 ++++------- test/helpers/EVMRevert.js | 5 --- test/helpers/EVMThrow.js | 5 --- test/helpers/assertJump.js | 15 -------- test/helpers/assertRevert.js | 16 -------- test/helpers/expectThrow.js | 28 -------------- test/helpers/shouldFail.js | 31 +++++++++++++++ test/introspection/ERC165.test.js | 4 +- test/library/ECDSA.test.js | 4 +- test/lifecycle/Pausable.test.js | 16 ++++---- test/math/SafeMath.test.js | 12 +++--- test/ownership/Ownable.behavior.js | 9 ++--- test/ownership/Secondary.test.js | 11 +++--- test/payment/ConditionalEscrow.test.js | 6 +-- test/payment/Escrow.behavior.js | 7 ++-- test/payment/RefundEscrow.test.js | 29 +++++++------- test/payment/SplitPayment.test.js | 19 +++++----- test/token/ERC20/ERC20.test.js | 36 +++++++++--------- test/token/ERC20/ERC20Capped.test.js | 4 +- test/token/ERC20/ERC20Pausable.test.js | 20 +++++----- test/token/ERC20/SafeERC20.test.js | 9 ++--- test/token/ERC20/TokenTimelock.test.js | 10 ++--- test/token/ERC20/TokenVesting.test.js | 22 +++-------- .../ERC20/behaviors/ERC20Burnable.behavior.js | 8 ++-- .../ERC20/behaviors/ERC20Capped.behavior.js | 6 +-- .../ERC20/behaviors/ERC20Mintable.behavior.js | 4 +- test/token/ERC721/ERC721.behavior.js | 38 +++++++++++-------- test/token/ERC721/ERC721Full.test.js | 20 +++++----- test/token/ERC721/ERC721MintBurn.behavior.js | 12 +++--- .../ERC721/ERC721PausedToken.behavior.js | 12 +++--- test/utils/ReentrancyGuard.test.js | 8 ++-- 46 files changed, 282 insertions(+), 352 deletions(-) delete mode 100644 test/helpers/EVMRevert.js delete mode 100644 test/helpers/EVMThrow.js delete mode 100644 test/helpers/assertJump.js delete mode 100644 test/helpers/assertRevert.js delete mode 100644 test/helpers/expectThrow.js create mode 100644 test/helpers/shouldFail.js diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js index 5995f64f5..77f11bb2b 100644 --- a/test/BreakInvariantBounty.test.js +++ b/test/BreakInvariantBounty.test.js @@ -3,7 +3,7 @@ const { ether } = require('./helpers/ether'); const { sendEther } = require('./helpers/sendTransaction'); const { balanceDifference } = require('./helpers/balanceDiff'); const expectEvent = require('./helpers/expectEvent'); -const { assertRevert } = require('./helpers/assertRevert'); +const shouldFail = require('./helpers/shouldFail'); const BreakInvariantBountyMock = artifacts.require('BreakInvariantBountyMock'); const TargetMock = artifacts.require('TargetMock'); @@ -48,7 +48,7 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar context('before exploiting vulnerability', async function () { it('reverts when claiming reward', async function () { - await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); + await shouldFail.reverting(this.bounty.claim(this.target.address, { from: researcher })); }); }); @@ -74,11 +74,11 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); it('no longer accepts rewards', async function () { - await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); + await shouldFail.reverting(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); }); it('reverts when reclaimed', async function () { - await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); + await shouldFail.reverting(this.bounty.claim(this.target.address, { from: researcher })); }); }); }); @@ -86,7 +86,7 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar context('with non-target', function () { it('reverts when claiming reward', async function () { - await assertRevert(this.bounty.claim(nonTarget, { from: researcher })); + await shouldFail.reverting(this.bounty.claim(nonTarget, { from: researcher })); }); }); }); @@ -105,7 +105,7 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); it('reverts when canceled by anyone', async function () { - await assertRevert(this.bounty.cancelBounty({ from: anyone })); + await shouldFail.reverting(this.bounty.cancelBounty({ from: anyone })); }); }); @@ -119,11 +119,11 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); it('no longer accepts rewards', async function () { - await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); + await shouldFail.reverting(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); }); it('reverts when recanceled', async function () { - await assertRevert(this.bounty.cancelBounty({ from: owner })); + await shouldFail.reverting(this.bounty.cancelBounty({ from: owner })); }); }); }); diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 76517492c..869217776 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const RolesMock = artifacts.require('RolesMock'); require('chai') @@ -11,7 +12,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when querying roles for the null account', async function () { - await assertRevert(this.roles.has(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.has(ZERO_ADDRESS)); }); context('initially', function () { @@ -35,7 +36,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when adding roles to the null account', async function () { - await assertRevert(this.roles.add(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.add(ZERO_ADDRESS)); }); }); }); @@ -58,7 +59,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when removing roles from the null account', async function () { - await assertRevert(this.roles.remove(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.remove(ZERO_ADDRESS)); }); }); }); diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index a3067f88e..57b94cf97 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const expectEvent = require('../../helpers/expectEvent'); @@ -20,7 +20,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when querying roles for the null account', async function () { - await assertRevert(this.contract[`is${rolename}`](ZERO_ADDRESS)); + await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS)); }); describe('access control', function () { @@ -36,7 +36,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role const from = anyone; it('reverts', async function () { - await assertRevert(this.contract[`only${rolename}Mock`]({ from })); + await shouldFail.reverting(this.contract[`only${rolename}Mock`]({ from })); }); }); }); @@ -58,7 +58,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when adding role to the null account', async function () { - await assertRevert(this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized })); + await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized })); }); }); @@ -79,7 +79,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when removing role from the null account', async function () { - await assertRevert(this.contract[`remove${rolename}`](ZERO_ADDRESS)); + await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS)); }); }); diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index c6f825126..4298dcce6 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,6 +1,6 @@ const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ethGetBalance } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -74,7 +74,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('when token wallet is different from token address', function () { it('creation reverts', async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - await assertRevert(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); + await shouldFail.reverting(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); }); }); }); diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index 5ccfafba3..a073d7a4e 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -1,6 +1,5 @@ const { ether } = require('../helpers/ether'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -22,10 +21,7 @@ contract('CappedCrowdsale', function ([_, wallet]) { }); it('rejects a cap of zero', async function () { - await expectThrow( - CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0), - EVMRevert, - ); + await shouldFail.reverting(CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0)); }); context('with crowdsale', function () { @@ -42,17 +38,11 @@ contract('CappedCrowdsale', function ([_, wallet]) { it('should reject payments outside cap', async function () { await this.crowdsale.send(cap); - await expectThrow( - this.crowdsale.send(1), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(1)); }); it('should reject payments that exceed cap', async function () { - await expectThrow( - this.crowdsale.send(cap.plus(1)), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(cap.plus(1))); }); }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index b1f3b381f..8875e9157 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,5 +1,5 @@ const expectEvent = require('../helpers/expectEvent'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -20,7 +20,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { const expectedTokenAmount = rate.mul(value); it('requires a non-null token', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(rate, wallet, ZERO_ADDRESS) ); }); @@ -31,13 +31,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('requires a non-zero rate', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(0, wallet, this.token.address) ); }); it('requires a non-null wallet', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(rate, ZERO_ADDRESS, this.token.address) ); }); @@ -55,7 +55,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('reverts on zero-valued payments', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.send(0, { from: purchaser }) ); }); @@ -67,13 +67,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('reverts on zero-valued payments', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.buyTokens(investor, { value: 0, from: purchaser }) ); }); it('requires a non-null beneficiary', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.buyTokens(ZERO_ADDRESS, { value: value, from: purchaser }) ); }); diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 6eea7f2f2..93d406432 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,8 +1,7 @@ const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -33,7 +32,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); it('cannot be finalized before ending', async function () { - await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.finalize({ from: anyone })); }); it('can be finalized by anyone after ending', async function () { @@ -44,7 +43,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { it('cannot be finalized twice', async function () { await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); - await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.finalize({ from: anyone })); }); it('logs finalized', async function () { diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 2024d7751..a76186bbc 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -1,7 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -35,13 +35,13 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('rejects a final rate larger than the initial rate', async function () { - await assertRevert(IncreasingPriceCrowdsaleImpl.new( + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); it('rejects a final rate of zero', async function () { - await assertRevert(IncreasingPriceCrowdsaleImpl.new( + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); }); diff --git a/test/crowdsale/IndividuallyCappedCrowdsale.test.js b/test/crowdsale/IndividuallyCappedCrowdsale.test.js index 70c01a6b9..c92fad466 100644 --- a/test/crowdsale/IndividuallyCappedCrowdsale.test.js +++ b/test/crowdsale/IndividuallyCappedCrowdsale.test.js @@ -1,6 +1,5 @@ const { ether } = require('../helpers/ether'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -42,7 +41,7 @@ contract('IndividuallyCappedCrowdsale', function ( }); it('reverts when a non-capper sets a cap', async function () { - await expectThrow(this.crowdsale.setCap(alice, capAlice, { from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.setCap(alice, capAlice, { from: anyone })); }); context('with individual caps', function () { @@ -60,21 +59,21 @@ contract('IndividuallyCappedCrowdsale', function ( it('should reject payments outside cap', async function () { await this.crowdsale.buyTokens(alice, { value: capAlice }); - await expectThrow(this.crowdsale.buyTokens(alice, { value: 1 }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: 1 })); }); it('should reject payments that exceed cap', async function () { - await expectThrow(this.crowdsale.buyTokens(alice, { value: capAlice.plus(1) }), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(bob, { value: capBob.plus(1) }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: capAlice.plus(1) })); + await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: capBob.plus(1) })); }); it('should manage independent caps', async function () { await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice }); - await expectThrow(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice })); }); it('should default to a cap of zero', async function () { - await expectThrow(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth })); }); }); diff --git a/test/crowdsale/MintedCrowdsale.test.js b/test/crowdsale/MintedCrowdsale.test.js index a3c846b2d..0b95f9ab8 100644 --- a/test/crowdsale/MintedCrowdsale.test.js +++ b/test/crowdsale/MintedCrowdsale.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeMintedCrowdsale } = require('./MintedCrowdsale.behavior'); const { ether } = require('../helpers/ether'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -35,11 +35,11 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] }); it('rejects bare payments', async function () { - await assertRevert(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.send(value)); }); it('rejects token purchases', async function () { - await assertRevert(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); }); }); }); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 866e4da15..723cb1fca 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -1,7 +1,6 @@ const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -51,7 +50,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { - await expectThrow(this.crowdsale.withdrawTokens(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); }); context('after closing time', function () { @@ -67,7 +66,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { it('rejects multiple withdrawals', async function () { await this.crowdsale.withdrawTokens(investor); - await expectThrow(this.crowdsale.withdrawTokens(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); }); }); }); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 77e0bfebb..6b863abad 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,8 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; @@ -35,11 +34,8 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('rejects a goal of zero', async function () { - await expectThrow( - RefundableCrowdsaleImpl.new( - this.openingTime, this.closingTime, rate, wallet, this.token.address, 0, - ), - EVMRevert, + await shouldFail.reverting( + RefundableCrowdsaleImpl.new(this.openingTime, this.closingTime, rate, wallet, this.token.address, 0) ); }); @@ -54,7 +50,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('before opening time', function () { it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); }); @@ -64,7 +60,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); context('with unreached goal', function () { @@ -99,7 +95,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); it('forwards funds to wallet', async function () { diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index cfbc3d3cf..eb2a9bf51 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -1,8 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); const BigNumber = web3.BigNumber; @@ -31,15 +30,15 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('rejects an opening time in the past', async function () { - await expectThrow(TimedCrowdsaleImpl.new( + await shouldFail.reverting(TimedCrowdsaleImpl.new( (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address - ), EVMRevert); + )); }); it('rejects a closing time before the opening time', async function () { - await expectThrow(TimedCrowdsaleImpl.new( + await shouldFail.reverting(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address - ), EVMRevert); + )); }); context('with crowdsale', function () { @@ -60,8 +59,8 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { describe('accepting payments', function () { it('should reject payments before start', async function () { (await this.crowdsale.isOpen()).should.equal(false); - await expectThrow(this.crowdsale.send(value), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { from: purchaser, value: value }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: purchaser, value: value })); }); it('should accept payments after start', async function () { @@ -73,8 +72,8 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { it('should reject payments after end', async function () { await time.increaseTo(this.afterClosingTime); - await expectThrow(this.crowdsale.send(value), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); }); }); }); diff --git a/test/drafts/ERC20Migrator.test.js b/test/drafts/ERC20Migrator.test.js index 608dce860..92763a219 100644 --- a/test/drafts/ERC20Migrator.test.js +++ b/test/drafts/ERC20Migrator.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const ERC20Mock = artifacts.require('ERC20Mock'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20Migrator = artifacts.require('ERC20Migrator'); @@ -14,7 +15,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { const totalSupply = 200; it('reverts with a null legacy token address', async function () { - await assertRevert(ERC20Migrator.new(ZERO_ADDRESS)); + await shouldFail.reverting(ERC20Migrator.new(ZERO_ADDRESS)); }); describe('with tokens and migrator', function () { @@ -30,11 +31,11 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { describe('beginMigration', function () { it('reverts with a null new token address', async function () { - await assertRevert(this.migrator.beginMigration(ZERO_ADDRESS)); + await shouldFail.reverting(this.migrator.beginMigration(ZERO_ADDRESS)); }); it('reverts if not a minter of the token', async function () { - await assertRevert(this.migrator.beginMigration(this.newToken.address)); + await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); }); it('succeeds if it is a minter of the token', async function () { @@ -45,7 +46,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { it('reverts the second time it is called', async function () { await this.newToken.addMinter(this.migrator.address); await this.migrator.beginMigration(this.newToken.address); - await assertRevert(this.migrator.beginMigration(this.newToken.address)); + await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); }); }); @@ -145,7 +146,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { const amount = baseAmount + 1; it('reverts', async function () { - await assertRevert(this.migrator.migrate(owner, amount)); + await shouldFail.reverting(this.migrator.migrate(owner, amount)); }); }); }); diff --git a/test/drafts/SignatureBouncer.test.js b/test/drafts/SignatureBouncer.test.js index c234687fc..e1bb294f3 100644 --- a/test/drafts/SignatureBouncer.test.js +++ b/test/drafts/SignatureBouncer.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { getSignFor } = require('../helpers/sign'); const { shouldBehaveLikePublicRole } = require('../access/roles/PublicRole.behavior'); @@ -36,19 +36,19 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: anyone }) ); }); it('does not allow valid signature for method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(this.signFor(authorizedUser, 'onlyWithValidSignature'), { from: authorizedUser }) ); @@ -63,13 +63,13 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature with correct method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature with correct method for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod( this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: anyone } ) @@ -77,14 +77,14 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid method signature with incorrect method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser, 'theWrongMethod'), { from: authorizedUser }) ); }); it('does not allow valid non-method signature method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser), { from: authorizedUser }) ); }); @@ -98,13 +98,13 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature with correct method and data for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature with correct method and incorrect data for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10, this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: authorizedUser } @@ -113,7 +113,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid signature with correct method and data for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: anyone } @@ -122,7 +122,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid non-method signature for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.signFor(authorizedUser), { from: authorizedUser } ) @@ -130,7 +130,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.tooShortMsgData({ from: authorizedUser }) ); }); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index 303ddf704..da367c970 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -1,9 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); -const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; @@ -53,14 +51,8 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); it('should not accept payments before start', async function () { - await expectThrow( - this.crowdsale.send(ether(1)), - EVMRevert, - ); - await expectThrow( - this.crowdsale.buyTokens(investor, { from: investor, value: ether(1) }), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(ether(1))); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: investor, value: ether(1) })); }); it('should accept payments during the sale', async function () { @@ -76,14 +68,14 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { it('should reject payments after end', async function () { await time.increaseTo(this.afterClosingTime); - await expectThrow(this.crowdsale.send(ether(1)), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(ether(1))); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor })); }); it('should reject payments over cap', async function () { await time.increaseTo(this.openingTime); await this.crowdsale.send(CAP); - await expectThrow(this.crowdsale.send(1), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(1)); }); it('should allow finalization and transfer funds to wallet if the goal is reached', async function () { @@ -117,7 +109,7 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { const HIGH_GOAL = ether(30); it('creation reverts', async function () { - await assertRevert(SampleCrowdsale.new( + await shouldFail.reverting(SampleCrowdsale.new( this.openingTime, this.closingTime, RATE, wallet, CAP, this.token.address, HIGH_GOAL )); }); diff --git a/test/helpers/EVMRevert.js b/test/helpers/EVMRevert.js deleted file mode 100644 index cb0c8e02e..000000000 --- a/test/helpers/EVMRevert.js +++ /dev/null @@ -1,5 +0,0 @@ -const EVMRevert = 'revert'; - -module.exports = { - EVMRevert, -}; diff --git a/test/helpers/EVMThrow.js b/test/helpers/EVMThrow.js deleted file mode 100644 index afe21d277..000000000 --- a/test/helpers/EVMThrow.js +++ /dev/null @@ -1,5 +0,0 @@ -const EVMThrow = 'invalid opcode'; - -module.exports = { - EVMThrow, -}; diff --git a/test/helpers/assertJump.js b/test/helpers/assertJump.js deleted file mode 100644 index 979307088..000000000 --- a/test/helpers/assertJump.js +++ /dev/null @@ -1,15 +0,0 @@ -const should = require('chai') - .should(); - -async function assertJump (promise) { - try { - await promise; - should.fail('Expected invalid opcode not received'); - } catch (error) { - error.message.should.include('invalid opcode', `Expected "invalid opcode", got ${error} instead`); - } -} - -module.exports = { - assertJump, -}; diff --git a/test/helpers/assertRevert.js b/test/helpers/assertRevert.js deleted file mode 100644 index 3d1aa2e16..000000000 --- a/test/helpers/assertRevert.js +++ /dev/null @@ -1,16 +0,0 @@ -const should = require('chai') - .should(); - -async function assertRevert (promise) { - try { - await promise; - } catch (error) { - error.message.should.include('revert', `Expected "revert", got ${error} instead`); - return; - } - should.fail('Expected revert not received'); -} - -module.exports = { - assertRevert, -}; diff --git a/test/helpers/expectThrow.js b/test/helpers/expectThrow.js deleted file mode 100644 index f46a981c8..000000000 --- a/test/helpers/expectThrow.js +++ /dev/null @@ -1,28 +0,0 @@ -const should = require('chai') - .should(); - -async function expectThrow (promise, message) { - try { - await promise; - } catch (error) { - // Message is an optional parameter here - if (message) { - error.message.should.include(message, 'Expected \'' + message + '\', got \'' + error + '\' instead'); - return; - } else { - // TODO: Check jump destination to destinguish between a throw - // and an actual invalid jump. - // TODO: When we contract A calls contract B, and B throws, instead - // of an 'invalid jump', we get an 'out of gas' error. How do - // we distinguish this from an actual out of gas event? (The - // ganache log actually show an 'invalid jump' event.) - error.message.should.match(/[invalid opcode|out of gas|revert]/, 'Expected throw, got \'' + error + '\' instead'); - return; - } - } - should.fail('Expected throw not received'); -} - -module.exports = { - expectThrow, -}; diff --git a/test/helpers/shouldFail.js b/test/helpers/shouldFail.js new file mode 100644 index 000000000..45e72f921 --- /dev/null +++ b/test/helpers/shouldFail.js @@ -0,0 +1,31 @@ +const should = require('chai') + .should(); + +async function shouldFailWithMessage (promise, message) { + try { + await promise; + } catch (error) { + error.message.should.include(message, 'Wrong failure type'); + return; + } + + should.fail(`Expected '${message}' failure not received`); +} + +async function reverting (promise) { + await shouldFailWithMessage(promise, 'revert'); +} + +async function throwing (promise) { + await shouldFailWithMessage(promise, 'invalid opcode'); +} + +async function outOfGas (promise) { + await shouldFailWithMessage(promise, 'out of gas'); +} + +module.exports = { + reverting, + throwing, + outOfGas, +}; diff --git a/test/introspection/ERC165.test.js b/test/introspection/ERC165.test.js index dc04edaa2..0dc2f8471 100644 --- a/test/introspection/ERC165.test.js +++ b/test/introspection/ERC165.test.js @@ -1,5 +1,5 @@ const { shouldSupportInterfaces } = require('./SupportsInterface.behavior'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const ERC165Mock = artifacts.require('ERC165Mock'); @@ -12,7 +12,7 @@ contract('ERC165', function () { }); it('does not allow 0xffffffff', async function () { - await assertRevert( + await shouldFail.reverting( this.mock.registerInterface(0xffffffff) ); }); diff --git a/test/library/ECDSA.test.js b/test/library/ECDSA.test.js index f8d333a5f..b07178b20 100644 --- a/test/library/ECDSA.test.js +++ b/test/library/ECDSA.test.js @@ -1,5 +1,5 @@ const { signMessage, toEthSignedMessageHash } = require('../helpers/sign'); -const { expectThrow } = require('../helpers/expectThrow'); +const shouldFail = require('../helpers/shouldFail'); const ECDSAMock = artifacts.require('ECDSAMock'); @@ -113,7 +113,7 @@ contract('ECDSA', function ([_, anyone]) { it.skip('reverts', async function () { // Create the signature const signature = signMessage(anyone, TEST_MESSAGE); - await expectThrow( + await shouldFail.reverting( this.ecdsa.recover(TEST_MESSAGE.substring(2), signature) ); }); diff --git a/test/lifecycle/Pausable.test.js b/test/lifecycle/Pausable.test.js index 2ae4c90d7..a7f6d637d 100644 --- a/test/lifecycle/Pausable.test.js +++ b/test/lifecycle/Pausable.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const PausableMock = artifacts.require('PausableMock'); @@ -37,7 +37,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('cannot take drastic measure in non-pause', async function () { - await assertRevert(this.pausable.drasticMeasure({ from: anyone })); + await shouldFail.reverting(this.pausable.drasticMeasure({ from: anyone })); (await this.pausable.drasticMeasureTaken()).should.equal(false); }); @@ -48,7 +48,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when pausing from non-pauser', async function () { - await assertRevert(this.pausable.pause({ from: anyone })); + await shouldFail.reverting(this.pausable.pause({ from: anyone })); }); context('when paused', function () { @@ -61,7 +61,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('cannot perform normal process in pause', async function () { - await assertRevert(this.pausable.normalProcess({ from: anyone })); + await shouldFail.reverting(this.pausable.normalProcess({ from: anyone })); }); it('can take a drastic measure in a pause', async function () { @@ -70,7 +70,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when re-pausing', async function () { - await assertRevert(this.pausable.pause({ from: pauser })); + await shouldFail.reverting(this.pausable.pause({ from: pauser })); }); describe('unpausing', function () { @@ -80,7 +80,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when unpausing from non-pauser', async function () { - await assertRevert(this.pausable.unpause({ from: anyone })); + await shouldFail.reverting(this.pausable.unpause({ from: anyone })); }); context('when unpaused', function () { @@ -99,11 +99,11 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('should prevent drastic measure', async function () { - await assertRevert(this.pausable.drasticMeasure({ from: anyone })); + await shouldFail.reverting(this.pausable.drasticMeasure({ from: anyone })); }); it('reverts when re-unpausing', async function () { - await assertRevert(this.pausable.unpause({ from: pauser })); + await shouldFail.reverting(this.pausable.unpause({ from: pauser })); }); }); }); diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index 56cedeb84..dcbb4fbb6 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { MAX_UINT256 } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -25,7 +25,7 @@ contract('SafeMath', function () { const a = MAX_UINT256; const b = new BigNumber(1); - await assertRevert(this.safeMath.add(a, b)); + await shouldFail.reverting(this.safeMath.add(a, b)); }); }); @@ -41,7 +41,7 @@ contract('SafeMath', function () { const a = new BigNumber(1234); const b = new BigNumber(5678); - await assertRevert(this.safeMath.sub(a, b)); + await shouldFail.reverting(this.safeMath.sub(a, b)); }); }); @@ -64,7 +64,7 @@ contract('SafeMath', function () { const a = MAX_UINT256; const b = new BigNumber(2); - await assertRevert(this.safeMath.mul(a, b)); + await shouldFail.reverting(this.safeMath.mul(a, b)); }); }); @@ -80,7 +80,7 @@ contract('SafeMath', function () { const a = new BigNumber(5678); const b = new BigNumber(0); - await assertRevert(this.safeMath.div(a, b)); + await shouldFail.reverting(this.safeMath.div(a, b)); }); }); @@ -119,7 +119,7 @@ contract('SafeMath', function () { const a = new BigNumber(5678); const b = new BigNumber(0); - await assertRevert(this.safeMath.mod(a, b)); + await shouldFail.reverting(this.safeMath.mod(a, b)); }); }); }); diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index 1e2fd7564..dd6007cef 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -22,11 +21,11 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('should prevent non-owners from transfering', async function () { - await expectThrow(this.ownable.transferOwnership(anyone, { from: anyone }), EVMRevert); + await shouldFail.reverting(this.ownable.transferOwnership(anyone, { from: anyone })); }); it('should guard ownership against stuck state', async function () { - await expectThrow(this.ownable.transferOwnership(null, { from: owner }), EVMRevert); + await shouldFail.reverting(this.ownable.transferOwnership(null, { from: owner })); }); it('loses owner after renouncement', async function () { @@ -37,7 +36,7 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('should prevent non-owners from renouncement', async function () { - await expectThrow(this.ownable.renounceOwnership({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.ownable.renounceOwnership({ from: anyone })); }); }); } diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 31676be79..55283963b 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const SecondaryMock = artifacts.require('SecondaryMock'); require('chai') @@ -20,7 +21,7 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when anyone calls onlyPrimary functions', async function () { - await assertRevert(this.secondary.onlyPrimaryMock({ from: anyone })); + await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: anyone })); }); }); @@ -31,11 +32,11 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when transfering to the null address', async function () { - await assertRevert(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary })); + await shouldFail.reverting(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary })); }); it('reverts when called by anyone', async function () { - await assertRevert(this.secondary.transferPrimary(newPrimary, { from: anyone })); + await shouldFail.reverting(this.secondary.transferPrimary(newPrimary, { from: anyone })); }); context('with new primary', function () { @@ -48,7 +49,7 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when the old primary account calls onlyPrimary functions', async function () { - await assertRevert(this.secondary.onlyPrimaryMock({ from: primary })); + await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: primary })); }); }); }); diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/ConditionalEscrow.test.js index 03eed68f7..bfb38dd86 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/ConditionalEscrow.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); + +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -34,7 +34,7 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) { it('reverts on withdrawals', async function () { await this.escrow.deposit(payee, { from: owner, value: amount }); - await expectThrow(this.escrow.withdraw(payee, { from: owner }), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(payee, { from: owner })); }); }); }); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 9769291e1..c724c5395 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -1,6 +1,5 @@ const expectEvent = require('../helpers/expectEvent'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ethGetBalance } = require('../helpers/web3'); const { ether } = require('../helpers/ether'); @@ -28,7 +27,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('only the primary account can deposit', async function () { - await expectThrow(this.escrow.deposit(payee1, { from: payee2 }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(payee1, { from: payee2 })); }); it('emits a deposited event', async function () { @@ -80,7 +79,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('only the primary account can withdraw', async function () { - await expectThrow(this.escrow.withdraw(payee1, { from: payee1 }), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(payee1, { from: payee1 })); }); it('emits a withdrawn event', async function () { diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index a3d669d69..123da9d82 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); const { ether } = require('../helpers/ether'); @@ -18,7 +17,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee const refundees = [refundee1, refundee2]; it('requires a non-null beneficiary', async function () { - await expectThrow( + await shouldFail.reverting( RefundEscrow.new(ZERO_ADDRESS, { from: primary }) ); }); @@ -42,17 +41,17 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('does not refund refundees', async function () { await this.escrow.deposit(refundee1, { from: primary, value: amount }); - await expectThrow(this.escrow.withdraw(refundee1), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(refundee1)); }); it('does not allow beneficiary withdrawal', async function () { await this.escrow.deposit(refundee1, { from: primary, value: amount }); - await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert); + await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); }); }); it('only the primary account can enter closed state', async function () { - await expectThrow(this.escrow.close({ from: beneficiary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: beneficiary })); const { logs } = await this.escrow.close({ from: primary }); expectEvent.inLogs(logs, 'Closed'); @@ -66,11 +65,11 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('rejects deposits', async function () { - await expectThrow(this.escrow.deposit(refundee1, { from: primary, value: amount }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); }); it('does not refund refundees', async function () { - await expectThrow(this.escrow.withdraw(refundee1), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(refundee1)); }); it('allows beneficiary withdrawal', async function () { @@ -82,16 +81,16 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('prevents entering the refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); }); it('prevents re-entering the closed state', async function () { - await expectThrow(this.escrow.close({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: primary })); }); }); it('only the primary account can enter refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: beneficiary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: beneficiary })); const { logs } = await this.escrow.enableRefunds({ from: primary }); expectEvent.inLogs(logs, 'RefundsEnabled'); @@ -105,7 +104,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('rejects deposits', async function () { - await expectThrow(this.escrow.deposit(refundee1, { from: primary, value: amount }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); }); it('refunds refundees', async function () { @@ -119,15 +118,15 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('does not allow beneficiary withdrawal', async function () { - await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert); + await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); }); it('prevents entering the closed state', async function () { - await expectThrow(this.escrow.close({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: primary })); }); it('prevents re-entering the refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); }); }); }); diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index c4a720fb9..6a10a5131 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -9,35 +9,34 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert.js'); +const shouldFail = require('../helpers/shouldFail'); const SplitPayment = artifacts.require('SplitPayment'); contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { const amount = ether(1.0); it('rejects an empty set of payees', async function () { - await expectThrow(SplitPayment.new([], []), EVMRevert); + await shouldFail.reverting(SplitPayment.new([], [])); }); it('rejects more payees than shares', async function () { - await expectThrow(SplitPayment.new([payee1, payee2, payee3], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2, payee3], [20, 30])); }); it('rejects more shares than payees', async function () { - await expectThrow(SplitPayment.new([payee1, payee2], [20, 30, 40]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 30, 40])); }); it('rejects null payees', async function () { - await expectThrow(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30])); }); it('rejects zero-valued shares', async function () { - await expectThrow(SplitPayment.new([payee1, payee2], [20, 0]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 0])); }); it('rejects repeated payees', async function () { - await expectThrow(SplitPayment.new([payee1, payee1], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee1], [20, 30])); }); context('once deployed', function () { @@ -74,12 +73,12 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should throw if no funds to claim', async function () { - await expectThrow(this.contract.release(payee1), EVMRevert); + await shouldFail.reverting(this.contract.release(payee1)); }); it('should throw if non-payee want to claim', async function () { await sendEther(payer1, this.contract.address, amount); - await expectThrow(this.contract.release(nonpayee1), EVMRevert); + await shouldFail.reverting(this.contract.release(nonpayee1)); }); it('should distribute funds to payees', async function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index e224de942..d60e9130c 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -43,7 +43,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transfer(to, amount, { from: owner })); + await shouldFail.reverting(this.token.transfer(to, amount, { from: owner })); }); }); @@ -74,7 +74,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const to = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.transfer(to, 100, { from: owner })); + await shouldFail.reverting(this.token.transfer(to, 100, { from: owner })); }); }); }); @@ -157,7 +157,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.approve(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.approve(spender, amount, { from: owner })); }); }); }); @@ -205,7 +205,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -219,7 +219,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 100; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); @@ -227,7 +227,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -242,7 +242,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -254,7 +254,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { function shouldDecreaseApproval (amount) { describe('when there was no approved amount before', function () { it('reverts', async function () { - await assertRevert(this.token.decreaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: owner })); }); }); @@ -287,7 +287,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('reverts when more than the full allowance is removed', async function () { - await assertRevert(this.token.decreaseAllowance(spender, approvedAmount + 1, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, approvedAmount + 1, { from: owner })); }); }); } @@ -310,7 +310,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.decreaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: owner })); }); }); }); @@ -392,7 +392,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.increaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.increaseAllowance(spender, amount, { from: owner })); }); }); }); @@ -402,7 +402,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = new BigNumber(50); it('rejects a null account', async function () { - await assertRevert(this.token.mint(ZERO_ADDRESS, amount)); + await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, amount)); }); describe('for a non null account', function () { @@ -435,12 +435,12 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const initialSupply = new BigNumber(100); it('rejects a null account', async function () { - await assertRevert(this.token.burn(ZERO_ADDRESS, 1)); + await shouldFail.reverting(this.token.burn(ZERO_ADDRESS, 1)); }); describe('for a non null account', function () { it('rejects burning more than balance', async function () { - await assertRevert(this.token.burn(owner, initialSupply.plus(1))); + await shouldFail.reverting(this.token.burn(owner, initialSupply.plus(1))); }); const describeBurn = function (description, amount) { @@ -487,16 +487,16 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('rejects a null account', async function () { - await assertRevert(this.token.burnFrom(ZERO_ADDRESS, 1)); + await shouldFail.reverting(this.token.burnFrom(ZERO_ADDRESS, 1)); }); describe('for a non null account', function () { it('rejects burning more than allowance', async function () { - await assertRevert(this.token.burnFrom(owner, allowance.plus(1))); + await shouldFail.reverting(this.token.burnFrom(owner, allowance.plus(1))); }); it('rejects burning more than balance', async function () { - await assertRevert(this.token.burnFrom(owner, initialSupply.plus(1))); + await shouldFail.reverting(this.token.burnFrom(owner, initialSupply.plus(1))); }); const describeBurnFrom = function (description, amount) { diff --git a/test/token/ERC20/ERC20Capped.test.js b/test/token/ERC20/ERC20Capped.test.js index 45558a162..dbb35e23b 100644 --- a/test/token/ERC20/ERC20Capped.test.js +++ b/test/token/ERC20/ERC20Capped.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ether } = require('../../helpers/ether'); const { shouldBehaveLikeERC20Mintable } = require('./behaviors/ERC20Mintable.behavior'); const { shouldBehaveLikeERC20Capped } = require('./behaviors/ERC20Capped.behavior'); @@ -9,7 +9,7 @@ contract('ERC20Capped', function ([_, minter, ...otherAccounts]) { const cap = ether(1000); it('requires a non-zero cap', async function () { - await assertRevert( + await shouldFail.reverting( ERC20Capped.new(0, { from: minter }) ); }); diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index a524e2442..05a0532ed 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,5 +1,5 @@ const expectEvent = require('../../helpers/expectEvent'); -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const ERC20PausableMock = artifacts.require('ERC20PausableMock'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); @@ -41,7 +41,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA }); it('reverts', async function () { - await assertRevert(this.token.pause({ from })); + await shouldFail.reverting(this.token.pause({ from })); }); }); }); @@ -50,7 +50,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA const from = anotherAccount; it('reverts', async function () { - await assertRevert(this.token.pause({ from })); + await shouldFail.reverting(this.token.pause({ from })); }); }); }); @@ -78,7 +78,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA describe('when the token is unpaused', function () { it('reverts', async function () { - await assertRevert(this.token.unpause({ from })); + await shouldFail.reverting(this.token.unpause({ from })); }); }); }); @@ -87,7 +87,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA const from = anotherAccount; it('reverts', async function () { - await assertRevert(this.token.unpause({ from })); + await shouldFail.reverting(this.token.unpause({ from })); }); }); }); @@ -133,7 +133,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.transfer(recipient, 100, { from: pauser })); + await shouldFail.reverting(this.token.transfer(recipient, 100, { from: pauser })); }); }); @@ -156,7 +156,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.approve(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.approve(anotherAccount, 40, { from: pauser })); }); }); @@ -185,7 +185,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer from when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.transferFrom(pauser, recipient, 40, { from: anotherAccount })); + await shouldFail.reverting(this.token.transferFrom(pauser, recipient, 40, { from: anotherAccount })); }); }); @@ -212,7 +212,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.decreaseAllowance(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.decreaseAllowance(anotherAccount, 40, { from: pauser })); }); }); @@ -239,7 +239,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to increase approval when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.increaseAllowance(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.increaseAllowance(anotherAccount, 40, { from: pauser })); }); }); }); diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index 6d61a2037..b6c87554b 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../../helpers/expectThrow'); -const { EVMRevert } = require('../../helpers/EVMRevert'); +const shouldFail = require('../../helpers/shouldFail'); require('chai') .should(); @@ -12,15 +11,15 @@ contract('SafeERC20', function () { }); it('should throw on failed transfer', async function () { - await expectThrow(this.helper.doFailingTransfer(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingTransfer()); }); it('should throw on failed transferFrom', async function () { - await expectThrow(this.helper.doFailingTransferFrom(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingTransferFrom()); }); it('should throw on failed approve', async function () { - await expectThrow(this.helper.doFailingApprove(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingApprove()); }); it('should not throw on succeeding transfer', async function () { diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index 04441fd1e..1816bf902 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -1,5 +1,5 @@ +const shouldFail = require('../../helpers/shouldFail'); const time = require('../../helpers/time'); -const { expectThrow } = require('../../helpers/expectThrow'); const BigNumber = web3.BigNumber; @@ -20,7 +20,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { it('rejects a release time in the past', async function () { const pastReleaseTime = (await time.latest()) - time.duration.years(1); - await expectThrow( + await shouldFail.reverting( TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime) ); }); @@ -39,12 +39,12 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('cannot be released before time limit', async function () { - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); }); it('cannot be released just before time limit', async function () { await time.increaseTo(this.releaseTime - time.duration.seconds(3)); - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); }); it('can be released just after limit', async function () { @@ -62,7 +62,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { it('cannot be released twice', async function () { await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); }); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index acfdb9adc..8fd767be1 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../../helpers/expectThrow'); -const { EVMRevert } = require('../../helpers/EVMRevert'); +const shouldFail = require('../../helpers/shouldFail'); const time = require('../../helpers/time'); const { ethGetBlock } = require('../../helpers/web3'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -29,13 +28,13 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { cliffDuration.should.be.gt(duration); - await expectThrow( + await shouldFail.reverting( TokenVesting.new(beneficiary, this.start, cliffDuration, duration, true, { from: owner }) ); }); it('requires a valid beneficiary', async function () { - await expectThrow( + await shouldFail.reverting( TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }) ); }); @@ -58,10 +57,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('cannot be released before cliff', async function () { - await expectThrow( - this.vesting.release(this.token.address), - EVMRevert, - ); + await shouldFail.reverting(this.vesting.release(this.token.address)); }); it('can be released after cliff', async function () { @@ -113,10 +109,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { beneficiary, this.start, this.cliffDuration, this.duration, false, { from: owner } ); - await expectThrow( - vesting.revoke(this.token.address, { from: owner }), - EVMRevert, - ); + await shouldFail.reverting(vesting.revoke(this.token.address, { from: owner })); }); it('should return the non-vested tokens when revoked by owner', async function () { @@ -148,10 +141,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { await this.vesting.revoke(this.token.address, { from: owner }); - await expectThrow( - this.vesting.revoke(this.token.address, { from: owner }), - EVMRevert, - ); + await shouldFail.reverting(this.vesting.revoke(this.token.address, { from: owner })); }); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 25af3254c..6e550afcb 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../../helpers/assertRevert'); +const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); @@ -42,7 +42,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = initialBalance + 1; it('reverts', async function () { - await assertRevert(this.token.burn(amount, { from: owner })); + await shouldFail.reverting(this.token.burn(amount, { from: owner })); }); }); }); @@ -88,7 +88,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = initialBalance + 1; it('reverts', async function () { await this.token.approve(burner, amount, { from: owner }); - await assertRevert(this.token.burnFrom(owner, amount, { from: burner })); + await shouldFail.reverting(this.token.burnFrom(owner, amount, { from: burner })); }); }); @@ -96,7 +96,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = 100; it('reverts', async function () { await this.token.approve(burner, amount - 1, { from: owner }); - await assertRevert(this.token.burnFrom(owner, amount, { from: burner })); + await shouldFail.reverting(this.token.burnFrom(owner, amount, { from: burner })); }); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Capped.behavior.js b/test/token/ERC20/behaviors/ERC20Capped.behavior.js index 3c3ab7fbf..e61db5702 100644 --- a/test/token/ERC20/behaviors/ERC20Capped.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Capped.behavior.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('../../../helpers/expectThrow'); +const shouldFail = require('../../../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -21,12 +21,12 @@ function shouldBehaveLikeERC20Capped (minter, [anyone], cap) { it('should fail to mint if the ammount exceeds the cap', async function () { await this.token.mint(anyone, cap.sub(1), { from }); - await expectThrow(this.token.mint(anyone, 100, { from })); + await shouldFail.reverting(this.token.mint(anyone, 100, { from })); }); it('should fail to mint after cap is reached', async function () { await this.token.mint(anyone, cap, { from }); - await expectThrow(this.token.mint(anyone, 1, { from })); + await shouldFail.reverting(this.token.mint(anyone, 1, { from })); }); }); } diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index f34504afc..bb8c0fe30 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../../helpers/assertRevert'); +const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); @@ -47,7 +47,7 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { const from = anyone; it('reverts', async function () { - await assertRevert(this.token.mint(anyone, amount, { from })); + await shouldFail.reverting(this.token.mint(anyone, amount, { from })); }); }); }); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index a18b6b437..aea385a99 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,6 +1,6 @@ const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); @@ -44,7 +44,7 @@ function shouldBehaveLikeERC721 ( context('when querying the zero address', function () { it('throws', async function () { - await assertRevert(this.token.balanceOf(0)); + await shouldFail.reverting(this.token.balanceOf(0)); }); }); }); @@ -62,7 +62,7 @@ function shouldBehaveLikeERC721 ( const tokenId = unknownTokenId; it('reverts', async function () { - await assertRevert(this.token.ownerOf(tokenId)); + await shouldFail.reverting(this.token.ownerOf(tokenId)); }); }); }); @@ -184,28 +184,28 @@ function shouldBehaveLikeERC721 ( context('when the address of the previous owner is incorrect', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, anyone, anyone, tokenId, { from: owner }) + await shouldFail.reverting(transferFunction.call(this, anyone, anyone, tokenId, { from: owner }) ); }); }); context('when the sender is not authorized for the token id', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, anyone, tokenId, { from: anyone }) + await shouldFail.reverting(transferFunction.call(this, owner, anyone, tokenId, { from: anyone }) ); }); }); context('when the given token ID does not exist', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner }) + await shouldFail.reverting(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner }) ); }); }); context('when the address to transfer the token to is the zero address', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner })); + await shouldFail.reverting(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner })); }); }); }; @@ -274,7 +274,7 @@ function shouldBehaveLikeERC721 ( describe('with an invalid token id', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( transferFun.call( this, owner, @@ -299,21 +299,27 @@ function shouldBehaveLikeERC721 ( describe('to a receiver contract returning unexpected value', function () { it('reverts', async function () { const invalidReceiver = await ERC721ReceiverMock.new('0x42', false); - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); describe('to a receiver contract that throws', function () { it('reverts', async function () { const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true); - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); describe('to a contract that does not implement the required function', function () { it('reverts', async function () { const invalidReceiver = this.token; - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); }); @@ -400,7 +406,7 @@ function shouldBehaveLikeERC721 ( context('when the address that receives the approval is the owner', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( this.token.approve(owner, tokenId, { from: owner }) ); }); @@ -408,14 +414,14 @@ function shouldBehaveLikeERC721 ( context('when the sender does not own the given token ID', function () { it('reverts', async function () { - await assertRevert(this.token.approve(approved, tokenId, { from: anyone })); + await shouldFail.reverting(this.token.approve(approved, tokenId, { from: anyone })); }); }); context('when the sender is approved for the given token ID', function () { it('reverts', async function () { await this.token.approve(approved, tokenId, { from: owner }); - await assertRevert(this.token.approve(anotherApproved, tokenId, { from: approved })); + await shouldFail.reverting(this.token.approve(anotherApproved, tokenId, { from: approved })); }); }); @@ -431,7 +437,7 @@ function shouldBehaveLikeERC721 ( context('when the given token ID does not exist', function () { it('reverts', async function () { - await assertRevert(this.token.approve(approved, unknownTokenId, { from: operator })); + await shouldFail.reverting(this.token.approve(approved, unknownTokenId, { from: operator })); }); }); }); @@ -509,7 +515,7 @@ function shouldBehaveLikeERC721 ( context('when the operator is the owner', function () { it('reverts', async function () { - await assertRevert(this.token.setApprovalForAll(owner, true, { from: owner })); + await shouldFail.reverting(this.token.setApprovalForAll(owner, true, { from: owner })); }); }); }); diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index 30e4547c8..6789ca28a 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); @@ -69,13 +69,13 @@ contract('ERC721Full', function ([ it('burns all tokens', async function () { await this.token.burn(secondTokenId, { from: owner }); (await this.token.totalSupply()).toNumber().should.be.equal(0); - await assertRevert(this.token.tokenByIndex(0)); + await shouldFail.reverting(this.token.tokenByIndex(0)); }); }); describe('removeTokenFrom', function () { it('reverts if the correct owner is not passed', async function () { - await assertRevert( + await shouldFail.reverting( this.token.removeTokenFrom(anyone, firstTokenId, { from: owner }) ); }); @@ -86,7 +86,7 @@ contract('ERC721Full', function ([ }); it('has been removed', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 1)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 1)); }); it('adjusts token list', async function () { @@ -120,7 +120,7 @@ contract('ERC721Full', function ([ }); it('reverts when setting metadata for non existent token id', async function () { - await assertRevert(this.token.setTokenURI(nonExistentTokenId, sampleUri)); + await shouldFail.reverting(this.token.setTokenURI(nonExistentTokenId, sampleUri)); }); it('can burn token with metadata', async function () { @@ -134,7 +134,7 @@ contract('ERC721Full', function ([ }); it('reverts when querying metadata for non existent token id', async function () { - await assertRevert(this.token.tokenURI(nonExistentTokenId)); + await shouldFail.reverting(this.token.tokenURI(nonExistentTokenId)); }); }); @@ -153,13 +153,13 @@ contract('ERC721Full', function ([ describe('when the index is greater than or equal to the total tokens owned by the given address', function () { it('reverts', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 2)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 2)); }); }); describe('when the given address does not own any token', function () { it('reverts', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(another, 0)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(another, 0)); }); }); @@ -179,7 +179,7 @@ contract('ERC721Full', function ([ it('returns empty collection for original owner', async function () { (await this.token.balanceOf(owner)).toNumber().should.be.equal(0); - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 0)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 0)); }); }); }); @@ -193,7 +193,7 @@ contract('ERC721Full', function ([ }); it('should revert if index is greater than supply', async function () { - await assertRevert(this.token.tokenByIndex(2)); + await shouldFail.reverting(this.token.tokenByIndex(2)); }); [firstTokenId, secondTokenId].forEach(function (tokenId) { diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index a5141abca..1bb7d1bc7 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -52,13 +52,13 @@ function shouldBehaveLikeMintAndBurnERC721 ( describe('when the given owner address is the zero address', function () { it('reverts', async function () { - await assertRevert(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); + await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); }); }); describe('when the given token ID was already tracked by this contract', function () { it('reverts', async function () { - await assertRevert(this.token.mint(owner, firstTokenId, { from: minter })); + await shouldFail.reverting(this.token.mint(owner, firstTokenId, { from: minter })); }); }); }); @@ -82,7 +82,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('burns the given token ID and adjusts the balance of the owner', async function () { - await assertRevert(this.token.ownerOf(tokenId)); + await shouldFail.reverting(this.token.ownerOf(tokenId)); (await this.token.balanceOf(owner)).should.be.bignumber.equal(1); }); @@ -104,14 +104,14 @@ function shouldBehaveLikeMintAndBurnERC721 ( context('getApproved', function () { it('reverts', async function () { - await assertRevert(this.token.getApproved(tokenId)); + await shouldFail.reverting(this.token.getApproved(tokenId)); }); }); }); describe('when the given token ID was not tracked by this contract', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( this.token.burn(unknownTokenId, { from: creator }) ); }); diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index a7196d837..1d83608fa 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { sendTransaction } = require('../../helpers/sendTransaction'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -19,23 +19,23 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { }); it('reverts when trying to approve', async function () { - await assertRevert(this.token.approve(recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.approve(recipient, firstTokenId, { from: owner })); }); it('reverts when trying to setApprovalForAll', async function () { - await assertRevert(this.token.setApprovalForAll(operator, true, { from: owner })); + await shouldFail.reverting(this.token.setApprovalForAll(operator, true, { from: owner })); }); it('reverts when trying to transferFrom', async function () { - await assertRevert(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner })); }); it('reverts when trying to safeTransferFrom', async function () { - await assertRevert(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner })); }); it('reverts when trying to safeTransferFrom with data', async function () { - await assertRevert( + await shouldFail.reverting( sendTransaction( this.token, 'safeTransferFrom', diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 3952b2fcb..16706fe8e 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); +const shouldFail = require('../helpers/shouldFail'); const ReentrancyMock = artifacts.require('ReentrancyMock'); const ReentrancyAttack = artifacts.require('ReentrancyAttack'); @@ -16,7 +16,7 @@ contract('ReentrancyGuard', function () { it('should not allow remote callback', async function () { const attacker = await ReentrancyAttack.new(); - await expectThrow(this.reentrancyMock.countAndCall(attacker.address)); + await shouldFail.reverting(this.reentrancyMock.countAndCall(attacker.address)); }); // The following are more side-effects than intended behavior: @@ -24,10 +24,10 @@ contract('ReentrancyGuard', function () { // in the side-effects. it('should not allow local recursion', async function () { - await expectThrow(this.reentrancyMock.countLocalRecursive(10)); + await shouldFail.reverting(this.reentrancyMock.countLocalRecursive(10)); }); it('should not allow indirect local recursion', async function () { - await expectThrow(this.reentrancyMock.countThisRecursive(10)); + await shouldFail.reverting(this.reentrancyMock.countThisRecursive(10)); }); }); From da67e435b17e370f70bd2b63a2178334b52627ac Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 10 Oct 2018 18:03:26 +0530 Subject: [PATCH 046/205] Non-constructor initialization removed (#1403) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1391 --- contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 6 +++++- contracts/lifecycle/Pausable.sol | 6 +++++- contracts/payment/SplitPayment.sol | 6 ++++-- contracts/utils/ReentrancyGuard.sol | 6 +++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index 37d205c8e..a640dca83 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -11,10 +11,14 @@ import "../validation/TimedCrowdsale.sol"; contract FinalizableCrowdsale is TimedCrowdsale { using SafeMath for uint256; - bool private _finalized = false; + bool private _finalized; event CrowdsaleFinalized(); + constructor() public { + _finalized = false; + } + /** * @return true if the crowdsale is finalized, false otherwise. */ diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 5287ecdcb..a6cae2a55 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -10,7 +10,11 @@ contract Pausable is PauserRole { event Paused(); event Unpaused(); - bool private _paused = false; + bool private _paused; + + constructor() public { + _paused = false; + } /** * @return true if the contract is paused, false otherwise. diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index 8bfcc7690..9c716e7ad 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -10,8 +10,8 @@ import "../math/SafeMath.sol"; contract SplitPayment { using SafeMath for uint256; - uint256 private _totalShares = 0; - uint256 private _totalReleased = 0; + uint256 private _totalShares; + uint256 private _totalReleased; mapping(address => uint256) private _shares; mapping(address => uint256) private _released; @@ -24,6 +24,8 @@ contract SplitPayment { require(payees.length == shares.length); require(payees.length > 0); + _totalShares = 0; + _totalReleased = 0; for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares[i]); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 63da3a99e..689c97205 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -9,7 +9,11 @@ pragma solidity ^0.4.24; contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation - uint256 private _guardCounter = 1; + uint256 private _guardCounter; + + constructor() public { + _guardCounter = 1; + } /** * @dev Prevents a contract from calling itself, directly or indirectly. From 076cb7decd2a5823af23648105e2aa72888fb32a Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 10 Oct 2018 12:06:22 -0600 Subject: [PATCH 047/205] Add a code style rule to make all state variables private (#1390) --- CODE_STYLE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CODE_STYLE.md b/CODE_STYLE.md index 2eaac05c9..d3337b16f 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -16,6 +16,8 @@ Any exception or additions specific to our project are documented below. * Try to avoid acronyms and abbreviations. +* All state variables should be private. + * Private state variables should have an underscore prefix. ``` From eb92fd1f48ce5a1fc4c4afc15a414b6d29aa7891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 10 Oct 2018 15:15:38 -0300 Subject: [PATCH 048/205] Fix typo in ARCHITECTURE.md (#1406) --- contracts/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/ARCHITECTURE.md b/contracts/ARCHITECTURE.md index 3d0ebfdaa..bfb6cff8d 100644 --- a/contracts/ARCHITECTURE.md +++ b/contracts/ARCHITECTURE.md @@ -12,7 +12,7 @@ The following provides visibility into how OpenZeppelin's contracts are organize - **introspection** - An interface that can be used to make a contract comply with the ERC-165 standard as well as a contract that implements ERC-165 using a lookup table. - **lifecycle** - A collection of base contracts used to manage the existence and behavior of your contracts and their funds. - **math** - Libraries with safety checks on operations that throw on errors. -- **mocks** - A collection of abstract contracts that are primarily used for unit testing. They also serve as good usage examples and demonstrate how to combine contracts with inheritence when developing your own custom applications. +- **mocks** - A collection of abstract contracts that are primarily used for unit testing. They also serve as good usage examples and demonstrate how to combine contracts with inheritance when developing your own custom applications. - **ownership** - A collection of smart contracts that can be used to manage contract and token ownership - **payment** - A collection of smart contracts that can be used to manage payments through escrow arrangements, withdrawals, and claims. Includes support for both single payees and multiple payees. - **proposals** - A collection of smart contracts that reflect community Ethereum Improvement Proposals (EIPs). These contracts are under development and standardization. They are not recommended for production, but they are useful for experimentation with pending EIP standards. Go [here](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/ERC-Process) for more information. From 9f822906b8e8e052bae7947d4c362fbabdd2c3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 10 Oct 2018 20:55:10 -0300 Subject: [PATCH 049/205] First test helpers tests (#1369) * Removed unused advanceToBlock. * Added advanceBlock tests. * Fixed advanceToBlock tests. * Added single argument tests. * Finished inLogs tests. * Fixed linter errors. * Fixed linter errors. --- contracts/mocks/EventEmitter.sol | 62 ++++++ test/helpers/advanceToBlock.js | 12 -- test/helpers/test/advanceToBlock.test.js | 19 ++ test/helpers/test/expectEvent.test.js | 232 +++++++++++++++++++++++ 4 files changed, 313 insertions(+), 12 deletions(-) create mode 100644 contracts/mocks/EventEmitter.sol create mode 100644 test/helpers/test/advanceToBlock.test.js create mode 100644 test/helpers/test/expectEvent.test.js diff --git a/contracts/mocks/EventEmitter.sol b/contracts/mocks/EventEmitter.sol new file mode 100644 index 000000000..71582d9f5 --- /dev/null +++ b/contracts/mocks/EventEmitter.sol @@ -0,0 +1,62 @@ +pragma solidity ^0.4.24; + +contract EventEmitter { + event Argumentless(); + event ShortUint(uint8 value); + event ShortInt(int8 value); + event LongUint(uint256 value); + event LongInt(int256 value); + event Address(address value); + event Boolean(bool value); + event String(string value); + event LongUintBooleanString( + uint256 uintValue, + bool booleanValue, + string stringValue + ); + + function emitArgumentless() public { + emit Argumentless(); + } + + function emitShortUint(uint8 value) public { + emit ShortUint(value); + } + + function emitShortInt(int8 value) public { + emit ShortInt(value); + } + + function emitLongUint(uint256 value) public { + emit LongUint(value); + } + + function emitLongInt(int256 value) public { + emit LongInt(value); + } + + function emitAddress(address value) public { + emit Address(value); + } + + function emitBoolean(bool value) public { + emit Boolean(value); + } + + function emitString(string value) public { + emit String(value); + } + + function emitLongUintBooleanString( + uint256 uintValue, + bool booleanValue, + string stringValue) + public { + emit LongUintBooleanString(uintValue, booleanValue, stringValue); + } + + function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public { + emit LongUint(uintValue); + emit Boolean(boolValue); + } +} diff --git a/test/helpers/advanceToBlock.js b/test/helpers/advanceToBlock.js index 22e5467cc..225502022 100644 --- a/test/helpers/advanceToBlock.js +++ b/test/helpers/advanceToBlock.js @@ -10,18 +10,6 @@ function advanceBlock () { }); } -// Advances the block number so that the last mined block is `number`. -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(); - } -} - module.exports = { advanceBlock, - advanceToBlock, }; diff --git a/test/helpers/test/advanceToBlock.test.js b/test/helpers/test/advanceToBlock.test.js new file mode 100644 index 000000000..cd8f1c352 --- /dev/null +++ b/test/helpers/test/advanceToBlock.test.js @@ -0,0 +1,19 @@ +const advanceToBlock = require('../advanceToBlock'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('advanceToBlock', function () { + beforeEach(function () { + this.startingBlock = web3.eth.blockNumber; + }); + + describe('advanceBlock', function () { + it('increases the block number by one', async function () { + await advanceToBlock.advanceBlock(); + web3.eth.blockNumber.should.be.bignumber.equal(this.startingBlock + 1); + }); + }); +}); diff --git a/test/helpers/test/expectEvent.test.js b/test/helpers/test/expectEvent.test.js new file mode 100644 index 000000000..158a9f374 --- /dev/null +++ b/test/helpers/test/expectEvent.test.js @@ -0,0 +1,232 @@ +const expectEvent = require('../expectEvent'); +const EventEmitter = artifacts.require('EventEmitter'); + +const BigNumber = web3.BigNumber; +const should = require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('expectEvent', function () { + beforeEach(async function () { + this.emitter = await EventEmitter.new(); + }); + + describe('inLogs', function () { + describe('with no arguments', function () { + beforeEach(async function () { + ({ logs: this.logs } = await this.emitter.emitArgumentless()); + }); + + it('accepts emitted events', function () { + expectEvent.inLogs(this.logs, 'Argumentless'); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent')); + }); + }); + + describe('with single argument', function () { + context('short uint value', function () { + beforeEach(async function () { + this.value = 42; + ({ logs: this.logs } = await this.emitter.emitShortUint(this.value)); + }); + + it('accepts emitted events with correct JavaScript number', function () { + expectEvent.inLogs(this.logs, 'ShortUint', { value: this.value }); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'ShortUint', { value: new BigNumber(this.value) }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'ShortUint', { value: 23 })); + }); + }); + + context('short int value', function () { + beforeEach(async function () { + this.value = -42; + ({ logs: this.logs } = await this.emitter.emitShortInt(this.value)); + }); + + it('accepts emitted events with correct JavaScript number', function () { + expectEvent.inLogs(this.logs, 'ShortInt', { value: this.value }); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'ShortInt', { value: new BigNumber(this.value) }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'ShortInt', { value: -23 })); + }); + }); + + context('long uint value', function () { + beforeEach(async function () { + this.bigNumValue = new BigNumber('123456789012345678901234567890'); + ({ logs: this.logs } = await this.emitter.emitLongUint(this.bigNumValue)); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'LongUint', { value: this.bigNumValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 2300 })); + }); + }); + + context('long int value', function () { + beforeEach(async function () { + this.bigNumValue = new BigNumber('-123456789012345678901234567890'); + ({ logs: this.logs } = await this.emitter.emitLongInt(this.bigNumValue)); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'LongInt', { value: this.bigNumValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongInt', { value: -2300 })); + }); + }); + + context('address value', function () { + beforeEach(async function () { + this.value = '0x811412068e9fbf25dc300a29e5e316f7122b282c'; + ({ logs: this.logs } = await this.emitter.emitAddress(this.value)); + }); + + it('accepts emitted events with correct address', function () { + expectEvent.inLogs(this.logs, 'Address', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => + expectEvent.inLogs(this.logs, 'Address', { value: '0x21d04e022e0b52b5d5bcf90b7f1aabf406be002d' }) + ); + }); + }); + + context('boolean value', function () { + beforeEach(async function () { + this.value = true; + ({ logs: this.logs } = await this.emitter.emitBoolean(this.value)); + }); + + it('accepts emitted events with correct address', function () { + expectEvent.inLogs(this.logs, 'Boolean', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false })); + }); + }); + + context('string value', function () { + beforeEach(async function () { + this.value = 'OpenZeppelin'; + ({ logs: this.logs } = await this.emitter.emitString(this.value)); + }); + + it('accepts emitted events with correct string', function () { + expectEvent.inLogs(this.logs, 'String', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'String', { value: 'ClosedZeppelin' })); + }); + }); + }); + + describe('with multiple arguments', function () { + beforeEach(async function () { + this.uintValue = new BigNumber('123456789012345678901234567890'); + this.booleanValue = true; + this.stringValue = 'OpenZeppelin'; + ({ logs: this.logs } = + await this.emitter.emitLongUintBooleanString(this.uintValue, this.booleanValue, this.stringValue)); + }); + + it('accepts correct values', function () { + expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: this.stringValue, + }); + }); + + it('throws with correct values assigned to wrong arguments', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.booleanValue, booleanValue: this.uintValue, stringValue: this.stringValue, + })); + }); + + it('throws when any of the values is incorrect', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: 23, booleanValue: this.booleanValue, stringValue: this.stringValue, + })); + + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: false, stringValue: this.stringValue, + })); + + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: 'ClosedZeppelin', + })); + }); + }); + + describe('with multiple events', function () { + beforeEach(async function () { + this.uintValue = 42; + this.booleanValue = true; + ({ logs: this.logs } = await this.emitter.emitLongUintAndBoolean(this.uintValue, this.booleanValue)); + }); + + it('accepts all emitted events with correct values', function () { + expectEvent.inLogs(this.logs, 'LongUint', { value: this.uintValue }); + expectEvent.inLogs(this.logs, 'Boolean', { value: this.booleanValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.uintValue })); + }); + + it('throws if incorrect values are passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 23 })); + should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false })); + }); + }); + }); +}); From 03dfb2965c6a607e216b110910f9fce1c43d8c94 Mon Sep 17 00:00:00 2001 From: Mikhail Melnik Date: Sat, 13 Oct 2018 01:13:36 +0300 Subject: [PATCH 050/205] Improve encapsulation on ERC165 and update code style guide (#1379) * use prefix underscore for internal state variables * make _supportedInterfaces private --- CODE_STYLE.md | 1 + contracts/introspection/ERC165.sol | 2 +- contracts/mocks/ERC165/ERC165InterfacesSupported.sol | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CODE_STYLE.md b/CODE_STYLE.md index d3337b16f..0c00a15a5 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -23,6 +23,7 @@ Any exception or additions specific to our project are documented below. ``` contract TestContract { uint256 private _privateVar; + uint256 internal _internalVar; } ``` diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 1af78d111..0c8637297 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -18,7 +18,7 @@ contract ERC165 is IERC165 { /** * @dev a mapping of interface id to whether or not it's supported */ - mapping(bytes4 => bool) internal _supportedInterfaces; + mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 1a06e9d52..e41901a32 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -21,7 +21,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { /** * @dev a mapping of interface id to whether or not it's supported */ - mapping(bytes4 => bool) internal supportedInterfaces; + mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup @@ -41,7 +41,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { view returns (bool) { - return supportedInterfaces[interfaceId]; + return _supportedInterfaces[interfaceId]; } /** @@ -51,7 +51,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { internal { require(interfaceId != 0xffffffff); - supportedInterfaces[interfaceId] = true; + _supportedInterfaces[interfaceId] = true; } } From 844a96d0b9419f5057bcae018b2a1974f075bc9d Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Tue, 16 Oct 2018 19:07:04 +0530 Subject: [PATCH 051/205] RefundEscrow's events renamed (#1418) * fixes #1414 --- contracts/payment/RefundEscrow.sol | 4 ++-- test/payment/RefundEscrow.test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/RefundEscrow.sol index c3770dbbb..3dfb3b965 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/RefundEscrow.sol @@ -11,7 +11,7 @@ import "./ConditionalEscrow.sol"; contract RefundEscrow is ConditionalEscrow { enum State { Active, Refunding, Closed } - event Closed(); + event RefundsClosed(); event RefundsEnabled(); State private _state; @@ -57,7 +57,7 @@ contract RefundEscrow is ConditionalEscrow { function close() public onlyPrimary { require(_state == State.Active); _state = State.Closed; - emit Closed(); + emit RefundsClosed(); } /** diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index 123da9d82..02a58a3b5 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -54,7 +54,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee await shouldFail.reverting(this.escrow.close({ from: beneficiary })); const { logs } = await this.escrow.close({ from: primary }); - expectEvent.inLogs(logs, 'Closed'); + expectEvent.inLogs(logs, 'RefundsClosed'); }); context('closed state', function () { From 3bd30f7382ee4a03ea342ff6a90db8f0d486522e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:20:33 -0300 Subject: [PATCH 052/205] Roles.add and remove now require pre-conditions on the account. (#1421) --- contracts/access/Roles.sol | 4 ++++ test/access/Roles.test.js | 9 ++++----- test/access/roles/PublicRole.behavior.js | 13 ++++++------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index 930a62066..e3b97ddb7 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -14,6 +14,8 @@ library Roles { */ function add(Role storage role, address account) internal { require(account != address(0)); + require(!has(role, account)); + role.bearer[account] = true; } @@ -22,6 +24,8 @@ library Roles { */ function remove(Role storage role, address account) internal { require(account != address(0)); + require(has(role, account)); + role.bearer[account] = false; } diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 869217776..4a3c7b09f 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -29,10 +29,9 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { (await this.roles.has(anyone)).should.equal(false); }); - it('adds roles to an already-assigned account', async function () { + it('reverts when adding roles to an already assigned account', async function () { await this.roles.add(authorized); - await this.roles.add(authorized); - (await this.roles.has(authorized)).should.equal(true); + await shouldFail.reverting(this.roles.add(authorized)); }); it('reverts when adding roles to the null account', async function () { @@ -54,8 +53,8 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { (await this.roles.has(otherAuthorized)).should.equal(true); }); - it('doesn\'t revert when removing unassigned roles', async function () { - await this.roles.remove(anyone); + it('reverts when removing unassigned roles', async function () { + await shouldFail.reverting(this.roles.remove(anyone)); }); it('reverts when removing roles from the null account', async function () { diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index 57b94cf97..0ae8a19e6 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -52,9 +52,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Added`, { account: anyone }); }); - it('adds role to an already-assigned account', async function () { - await this.contract[`add${rolename}`](authorized, { from: authorized }); - (await this.contract[`is${rolename}`](authorized)).should.equal(true); + it('reverts when adding role to an already assigned account', async function () { + await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from: authorized })); }); it('reverts when adding role to the null account', async function () { @@ -74,8 +73,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); }); - it('doesn\'t revert when removing from an unassigned account', async function () { - await this.contract[`remove${rolename}`](anyone); + it('reverts when removing from an unassigned account', async function () { + await shouldFail.reverting(this.contract[`remove${rolename}`](anyone)); }); it('reverts when removing role from the null account', async function () { @@ -94,8 +93,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); }); - it('doesn\'t revert when renouncing unassigned role', async function () { - await this.contract[`renounce${rolename}`]({ from: anyone }); + it('reverts when renouncing unassigned role', async function () { + await shouldFail.reverting(this.contract[`renounce${rolename}`]({ from: anyone })); }); }); }); From 3341dd88994ee468c6b36a1affa4608dedab7a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:20:55 -0300 Subject: [PATCH 053/205] Fixed a typo in a comment. (#1422) --- contracts/introspection/ERC165.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 0c8637297..60bcd53f3 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -42,7 +42,7 @@ contract ERC165 is IERC165 { } /** - * @dev private method for registering an interface + * @dev internal method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal From a3e312d133f9df1942b96b39cd007c883cd0331f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:21:08 -0300 Subject: [PATCH 054/205] Added Math.sol docstrings. (#1423) --- contracts/math/Math.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index d51a720c9..ffff83961 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -5,14 +5,25 @@ pragma solidity ^0.4.24; * @dev Assorted math operations */ library Math { + /** + * @dev Returns the largest of two numbers. + */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } + /** + * @dev Returns the smallest of two numbers. + */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } + /** + * @dev Calculates the average of two numbers. Since these are integers, + * averages of an even and odd number cannot be represented, and will be + * rounded down. + */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); From 9be0f100c48e4726bee73829fbb10f7d85b6ef54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:21:24 -0300 Subject: [PATCH 055/205] Removed BreakInvariantBounty. (#1424) --- contracts/bounties/BreakInvariantBounty.sol | 93 ------------- contracts/mocks/BreakInvariantBountyMock.sol | 28 ---- test/BreakInvariantBounty.test.js | 131 ------------------- 3 files changed, 252 deletions(-) delete mode 100644 contracts/bounties/BreakInvariantBounty.sol delete mode 100644 contracts/mocks/BreakInvariantBountyMock.sol delete mode 100644 test/BreakInvariantBounty.test.js diff --git a/contracts/bounties/BreakInvariantBounty.sol b/contracts/bounties/BreakInvariantBounty.sol deleted file mode 100644 index 6dec45a3b..000000000 --- a/contracts/bounties/BreakInvariantBounty.sol +++ /dev/null @@ -1,93 +0,0 @@ -pragma solidity ^0.4.24; - -import "../payment/PullPayment.sol"; -import "../ownership/Ownable.sol"; - -/** - * @title BreakInvariantBounty - * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. - */ -contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimable; - mapping(address => address) private _researchers; - - event TargetCreated(address createdAddress); - event BountyCanceled(); - - constructor() public { - _claimable = true; - } - - /** - * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. - */ - function() external payable { - require(_claimable); - } - - /** - * @dev Determine if the bounty is claimable. - * @return false if the bounty was claimed, true otherwise. - */ - function claimable() public view returns(bool) { - return _claimable; - } - - /** - * @dev Create and deploy the target contract (extension of Target contract), and sets the - * msg.sender as a researcher - * @return A target contract - */ - function createTarget() public returns(Target) { - Target target = Target(_deployContract()); - _researchers[target] = msg.sender; - emit TargetCreated(target); - return target; - } - - /** - * @dev Transfers the contract funds to the researcher that proved the contract is broken. - * @param target contract - */ - function claim(Target target) public { - require(_claimable); - address researcher = _researchers[target]; - require(researcher != address(0)); - // Check Target contract invariants - require(!target.checkInvariant()); - _asyncTransfer(researcher, address(this).balance); - _claimable = false; - } - - /** - * @dev Cancels the bounty and transfers all funds to the owner - */ - function cancelBounty() public onlyOwner{ - require(_claimable); - _asyncTransfer(owner(), address(this).balance); - _claimable = false; - emit BountyCanceled(); - } - - /** - * @dev Internal function to deploy the target contract. - * @return A target contract address - */ - function _deployContract() internal returns(address); - -} - -/** - * @title Target - * @dev Your main contract should inherit from this class and implement the checkInvariant method. - */ -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. - */ - function checkInvariant() public returns(bool); -} diff --git a/contracts/mocks/BreakInvariantBountyMock.sol b/contracts/mocks/BreakInvariantBountyMock.sol deleted file mode 100644 index 9343ef012..000000000 --- a/contracts/mocks/BreakInvariantBountyMock.sol +++ /dev/null @@ -1,28 +0,0 @@ -pragma solidity ^0.4.24; - -// When this line is split, truffle parsing fails. -// See: https://github.com/ethereum/solidity/issues/4871 -// solium-disable-next-line max-len -import {BreakInvariantBounty, Target} from "../bounties/BreakInvariantBounty.sol"; - -contract TargetMock is Target { - bool private exploited; - - function exploitVulnerability() public { - exploited = true; - } - - function checkInvariant() public returns (bool) { - if (exploited) { - return false; - } - - return true; - } -} - -contract BreakInvariantBountyMock is BreakInvariantBounty { - function _deployContract() internal returns (address) { - return new TargetMock(); - } -} diff --git a/test/BreakInvariantBounty.test.js b/test/BreakInvariantBounty.test.js deleted file mode 100644 index 77f11bb2b..000000000 --- a/test/BreakInvariantBounty.test.js +++ /dev/null @@ -1,131 +0,0 @@ -const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); -const { ether } = require('./helpers/ether'); -const { sendEther } = require('./helpers/sendTransaction'); -const { balanceDifference } = require('./helpers/balanceDiff'); -const expectEvent = require('./helpers/expectEvent'); -const shouldFail = require('./helpers/shouldFail'); - -const BreakInvariantBountyMock = artifacts.require('BreakInvariantBountyMock'); -const TargetMock = artifacts.require('TargetMock'); - -require('chai') - .use(require('chai-bignumber')(web3.BigNumber)) - .should(); - -const reward = ether(1); - -contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTarget]) { - beforeEach(async function () { - this.bounty = await BreakInvariantBountyMock.new({ from: owner }); - }); - - it('can set reward', async function () { - await sendEther(owner, this.bounty.address, reward); - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(reward); - }); - - context('with reward', function () { - beforeEach(async function () { - await sendEther(owner, this.bounty.address, reward); - }); - - describe('claim', function () { - it('is initially claimable', async function () { - (await this.bounty.claimable()).should.equal(true); - }); - - it('can create claimable target', async function () { - const { logs } = await this.bounty.createTarget({ from: researcher }); - expectEvent.inLogs(logs, 'TargetCreated'); - }); - - context('with target', async function () { - beforeEach(async function () { - const { logs } = await this.bounty.createTarget({ from: researcher }); - const event = expectEvent.inLogs(logs, 'TargetCreated'); - this.target = TargetMock.at(event.args.createdAddress); - }); - - context('before exploiting vulnerability', async function () { - it('reverts when claiming reward', async function () { - await shouldFail.reverting(this.bounty.claim(this.target.address, { from: researcher })); - }); - }); - - context('after exploiting vulnerability', async function () { - beforeEach(async function () { - await this.target.exploitVulnerability({ from: researcher }); - }); - - it('sends the reward to the researcher', async function () { - await this.bounty.claim(this.target.address, { from: anyone }); - (await balanceDifference(researcher, () => this.bounty.withdrawPayments(researcher))) - .should.be.bignumber.equal(reward); - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); - }); - - context('after claiming', async function () { - beforeEach(async function () { - await this.bounty.claim(this.target.address, { from: researcher }); - }); - - it('is not claimable', async function () { - (await this.bounty.claimable()).should.equal(false); - }); - - it('no longer accepts rewards', async function () { - await shouldFail.reverting(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); - }); - - it('reverts when reclaimed', async function () { - await shouldFail.reverting(this.bounty.claim(this.target.address, { from: researcher })); - }); - }); - }); - }); - - context('with non-target', function () { - it('reverts when claiming reward', async function () { - await shouldFail.reverting(this.bounty.claim(nonTarget, { from: researcher })); - }); - }); - }); - - describe('cancelBounty', function () { - context('before canceling', function () { - it('is claimable', async function () { - (await this.bounty.claimable()).should.equal(true); - }); - - it('can be canceled by the owner', async function () { - const { logs } = await this.bounty.cancelBounty({ from: owner }); - expectEvent.inLogs(logs, 'BountyCanceled'); - (await balanceDifference(owner, () => this.bounty.withdrawPayments(owner))) - .should.be.bignumber.equal(reward); - }); - - it('reverts when canceled by anyone', async function () { - await shouldFail.reverting(this.bounty.cancelBounty({ from: anyone })); - }); - }); - - context('after canceling', async function () { - beforeEach(async function () { - await this.bounty.cancelBounty({ from: owner }); - }); - - it('is not claimable', async function () { - (await this.bounty.claimable()).should.equal(false); - }); - - it('no longer accepts rewards', async function () { - await shouldFail.reverting(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); - }); - - it('reverts when recanceled', async function () { - await shouldFail.reverting(this.bounty.cancelBounty({ from: owner })); - }); - }); - }); - }); -}); From 03765e08b95afe9bd47544a4ec870ba37eb53420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Winnicki?= Date: Wed, 17 Oct 2018 16:35:31 +0200 Subject: [PATCH 056/205] Make state variables private (#1426) * added function to renounce ownership * Make state variables private (#1411) --- contracts/token/ERC721/ERC721Metadata.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 8334160aa..4fb35543c 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -6,10 +6,10 @@ import "../../introspection/ERC165.sol"; contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name - string internal _name; + string private _name; // Token symbol - string internal _symbol; + string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; From 2733cb4a411cf34e1a027ec5799298aa39ff549a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 16:58:36 -0300 Subject: [PATCH 057/205] Now using hex for asm memory addresses. (#1429) --- contracts/cryptography/ECDSA.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 3f0ad1bd2..71c0e41ed 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -33,9 +33,9 @@ library ECDSA { // currently is to use assembly. // solium-disable-next-line security/no-inline-assembly assembly { - r := mload(add(signature, 32)) - s := mload(add(signature, 64)) - v := byte(0, mload(add(signature, 96))) + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) } // Version of signature should be 27 or 28, but 0 and 1 are also possible versions From d8ab8a00f2cb3c066d17531aaf2403d0a5ba9c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 16:58:49 -0300 Subject: [PATCH 058/205] Moved some test files around to better reflect the directory layout. (#1428) --- test/{library => cryptography}/ECDSA.test.js | 0 test/{library => cryptography}/MerkleProof.test.js | 0 test/{token/ERC20 => drafts}/TokenVesting.test.js | 8 ++++---- test/{library => math}/Math.test.js | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename test/{library => cryptography}/ECDSA.test.js (100%) rename test/{library => cryptography}/MerkleProof.test.js (100%) rename test/{token/ERC20 => drafts}/TokenVesting.test.js (96%) rename test/{library => math}/Math.test.js (100%) diff --git a/test/library/ECDSA.test.js b/test/cryptography/ECDSA.test.js similarity index 100% rename from test/library/ECDSA.test.js rename to test/cryptography/ECDSA.test.js diff --git a/test/library/MerkleProof.test.js b/test/cryptography/MerkleProof.test.js similarity index 100% rename from test/library/MerkleProof.test.js rename to test/cryptography/MerkleProof.test.js diff --git a/test/token/ERC20/TokenVesting.test.js b/test/drafts/TokenVesting.test.js similarity index 96% rename from test/token/ERC20/TokenVesting.test.js rename to test/drafts/TokenVesting.test.js index 8fd767be1..37864fbca 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -1,7 +1,7 @@ -const shouldFail = require('../../helpers/shouldFail'); -const time = require('../../helpers/time'); -const { ethGetBlock } = require('../../helpers/web3'); -const { ZERO_ADDRESS } = require('../../helpers/constants'); +const shouldFail = require('../helpers/shouldFail'); +const time = require('../helpers/time'); +const { ethGetBlock } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; diff --git a/test/library/Math.test.js b/test/math/Math.test.js similarity index 100% rename from test/library/Math.test.js rename to test/math/Math.test.js From cfef58361f8c79daf684f084d04faac6e294dba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 17:00:12 -0300 Subject: [PATCH 059/205] Removed default value assignments. (#1432) --- contracts/drafts/ERC1046/TokenMetadata.sol | 2 +- contracts/payment/SplitPayment.sol | 2 -- contracts/utils/ReentrancyGuard.sol | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index 85b6ec671..9057711d9 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -13,7 +13,7 @@ contract ERC20TokenMetadata is IERC20 { } contract ERC20WithMetadata is ERC20TokenMetadata { - string private _tokenURI = ""; + string private _tokenURI; constructor(string tokenURI) public diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index 9c716e7ad..960772182 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -24,8 +24,6 @@ contract SplitPayment { require(payees.length == shares.length); require(payees.length > 0); - _totalShares = 0; - _totalReleased = 0; for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares[i]); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 689c97205..4c10dc775 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -12,6 +12,8 @@ contract ReentrancyGuard { uint256 private _guardCounter; constructor() public { + // The counter starts at one to prevent changing it from zero to a non-zero + // value, which is a more expensive operation. _guardCounter = 1; } From f3df2dab3d28b14242dbffd98f10c8181ed7dfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 17:22:25 -0300 Subject: [PATCH 060/205] Moved Escrows into an escrow subdirectory, improved docs. (#1430) * Moved Escrows into an escrow subdirectory, improved docs. * Fixed escrow mock. * Fixed some more imports. --- .../distribution/RefundableCrowdsale.sol | 2 +- contracts/mocks/ConditionalEscrowMock.sol | 2 +- contracts/payment/PullPayment.sol | 2 +- .../{ => escrow}/ConditionalEscrow.sol | 1 + contracts/payment/{ => escrow}/Escrow.sol | 19 ++++++++++++------- .../payment/{ => escrow}/RefundEscrow.sol | 11 ++++++++--- .../{ => escrow}/ConditionalEscrow.test.js | 4 ++-- test/payment/{ => escrow}/Escrow.behavior.js | 8 ++++---- test/payment/{ => escrow}/Escrow.test.js | 0 .../payment/{ => escrow}/RefundEscrow.test.js | 10 +++++----- 10 files changed, 35 insertions(+), 24 deletions(-) rename contracts/payment/{ => escrow}/ConditionalEscrow.sol (88%) rename contracts/payment/{ => escrow}/Escrow.sol (60%) rename contracts/payment/{ => escrow}/RefundEscrow.sol (81%) rename test/payment/{ => escrow}/ConditionalEscrow.test.js (91%) rename test/payment/{ => escrow}/Escrow.behavior.js (93%) rename test/payment/{ => escrow}/Escrow.test.js (100%) rename test/payment/{ => escrow}/RefundEscrow.test.js (94%) diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index a69d4a0ed..d55a573fb 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "./FinalizableCrowdsale.sol"; -import "../../payment/RefundEscrow.sol"; +import "../../payment/escrow/RefundEscrow.sol"; /** * @title RefundableCrowdsale diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 93a594b97..3e30c21a2 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../payment/ConditionalEscrow.sol"; +import "../payment/escrow/ConditionalEscrow.sol"; // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 67ef8c667..4db11c089 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./Escrow.sol"; +import "./escrow/Escrow.sol"; /** * @title PullPayment diff --git a/contracts/payment/ConditionalEscrow.sol b/contracts/payment/escrow/ConditionalEscrow.sol similarity index 88% rename from contracts/payment/ConditionalEscrow.sol rename to contracts/payment/escrow/ConditionalEscrow.sol index 645dad479..c3f63ee37 100644 --- a/contracts/payment/ConditionalEscrow.sol +++ b/contracts/payment/escrow/ConditionalEscrow.sol @@ -5,6 +5,7 @@ import "./Escrow.sol"; /** * @title ConditionalEscrow * @dev Base abstract escrow to only allow withdrawal if a condition is met. + * @dev Intended usage: See Escrow.sol. Same usage guidelines apply here. */ contract ConditionalEscrow is Escrow { /** diff --git a/contracts/payment/Escrow.sol b/contracts/payment/escrow/Escrow.sol similarity index 60% rename from contracts/payment/Escrow.sol rename to contracts/payment/escrow/Escrow.sol index 7fb118e3a..b2f2a85ee 100644 --- a/contracts/payment/Escrow.sol +++ b/contracts/payment/escrow/Escrow.sol @@ -1,14 +1,19 @@ pragma solidity ^0.4.24; -import "../math/SafeMath.sol"; -import "../ownership/Secondary.sol"; +import "../../math/SafeMath.sol"; +import "../../ownership/Secondary.sol"; -/** + /** * @title Escrow - * @dev Base escrow contract, holds funds destinated to a payee until they - * withdraw them. The contract that uses the escrow as its payment method - * should be its primary, and provide public methods redirecting to the escrow's - * deposit and withdraw. + * @dev Base escrow contract, holds funds designated for a payee until they + * withdraw them. + * @dev Intended usage: This contract (and derived escrow contracts) should be a + * standalone contract, that only interacts with the contract that instantiated + * it. That way, it is guaranteed that all Ether will be handled according to + * the Escrow rules, and there is no need to check for payable functions or + * transfers in the inheritance tree. The contract that uses the escrow as its + * payment method should be its primary, and provide public methods redirecting + * to the escrow's deposit and withdraw. */ contract Escrow is Secondary { using SafeMath for uint256; diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/escrow/RefundEscrow.sol similarity index 81% rename from contracts/payment/RefundEscrow.sol rename to contracts/payment/escrow/RefundEscrow.sol index 3dfb3b965..a776a81c8 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/escrow/RefundEscrow.sol @@ -4,9 +4,14 @@ import "./ConditionalEscrow.sol"; /** * @title RefundEscrow - * @dev Escrow that holds funds for a beneficiary, deposited from multiple parties. - * The primary account may close the deposit period, and allow for either withdrawal - * by the beneficiary, or refunds to the depositors. + * @dev Escrow that holds funds for a beneficiary, deposited from multiple + * parties. + * @dev Intended usage: See Escrow.sol. Same usage guidelines apply here. + * @dev The primary account (that is, the contract that instantiates this + * contract) may deposit, close the deposit period, and allow for either + * withdrawal by the beneficiary, or refunds to the depositors. All interactions + * with RefundEscrow will be made through the primary contract. See the + * RefundableCrowdsale contract for an example of RefundEscrow’s use. */ contract RefundEscrow is ConditionalEscrow { enum State { Active, Refunding, Closed } diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/escrow/ConditionalEscrow.test.js similarity index 91% rename from test/payment/ConditionalEscrow.test.js rename to test/payment/escrow/ConditionalEscrow.test.js index bfb38dd86..c30b7bde5 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/escrow/ConditionalEscrow.test.js @@ -1,7 +1,7 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); -const shouldFail = require('../helpers/shouldFail'); -const { ether } = require('../helpers/ether'); +const shouldFail = require('../../helpers/shouldFail'); +const { ether } = require('../../helpers/ether'); const BigNumber = web3.BigNumber; diff --git a/test/payment/Escrow.behavior.js b/test/payment/escrow/Escrow.behavior.js similarity index 93% rename from test/payment/Escrow.behavior.js rename to test/payment/escrow/Escrow.behavior.js index c724c5395..d7a7975e7 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/escrow/Escrow.behavior.js @@ -1,7 +1,7 @@ -const expectEvent = require('../helpers/expectEvent'); -const shouldFail = require('../helpers/shouldFail'); -const { ethGetBalance } = require('../helpers/web3'); -const { ether } = require('../helpers/ether'); +const expectEvent = require('../../helpers/expectEvent'); +const shouldFail = require('../../helpers/shouldFail'); +const { ethGetBalance } = require('../../helpers/web3'); +const { ether } = require('../../helpers/ether'); const BigNumber = web3.BigNumber; diff --git a/test/payment/Escrow.test.js b/test/payment/escrow/Escrow.test.js similarity index 100% rename from test/payment/Escrow.test.js rename to test/payment/escrow/Escrow.test.js diff --git a/test/payment/RefundEscrow.test.js b/test/payment/escrow/RefundEscrow.test.js similarity index 94% rename from test/payment/RefundEscrow.test.js rename to test/payment/escrow/RefundEscrow.test.js index 02a58a3b5..1f92e23af 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/escrow/RefundEscrow.test.js @@ -1,8 +1,8 @@ -const shouldFail = require('../helpers/shouldFail'); -const expectEvent = require('../helpers/expectEvent'); -const { ethGetBalance } = require('../helpers/web3'); -const { ether } = require('../helpers/ether'); -const { ZERO_ADDRESS } = require('../helpers/constants'); +const shouldFail = require('../../helpers/shouldFail'); +const expectEvent = require('../../helpers/expectEvent'); +const { ethGetBalance } = require('../../helpers/web3'); +const { ether } = require('../../helpers/ether'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; From df3c1137119892afde07df98a2157ba24c565589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 18:18:41 -0300 Subject: [PATCH 061/205] Made some TokenVesting public functions private. (#1427) * Made some TokenVesting public functions private. * Fixed linter error. --- contracts/drafts/TokenVesting.sol | 10 +++++----- test/drafts/TokenVesting.test.js | 15 +++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index b97b60b2b..965ace102 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -114,7 +114,7 @@ contract TokenVesting is Ownable { * @param token ERC20 token which is being vested */ function release(IERC20 token) public { - uint256 unreleased = releasableAmount(token); + uint256 unreleased = _releasableAmount(token); require(unreleased > 0); @@ -136,7 +136,7 @@ contract TokenVesting is Ownable { uint256 balance = token.balanceOf(address(this)); - uint256 unreleased = releasableAmount(token); + uint256 unreleased = _releasableAmount(token); uint256 refund = balance.sub(unreleased); _revoked[token] = true; @@ -150,15 +150,15 @@ 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 releasableAmount(IERC20 token) public view returns (uint256) { - return vestedAmount(token).sub(_released[token]); + function _releasableAmount(IERC20 token) private view 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(IERC20 token) public view returns (uint256) { + function _vestedAmount(IERC20 token) private view returns (uint256) { uint256 currentBalance = token.balanceOf(this); uint256 totalBalance = currentBalance.add(_released[token]); diff --git a/test/drafts/TokenVesting.test.js b/test/drafts/TokenVesting.test.js index 37864fbca..c43a0d8b8 100644 --- a/test/drafts/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -115,7 +115,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('should return the non-vested tokens when revoked by owner', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - const vested = await this.vesting.vestedAmount(this.token.address); + const vested = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); await this.vesting.revoke(this.token.address, { from: owner }); @@ -125,23 +125,22 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('should keep the vested tokens when revoked by owner', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - const vestedPre = await this.vesting.vestedAmount(this.token.address); + const vestedPre = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); await this.vesting.revoke(this.token.address, { from: owner }); - const vestedPost = await this.vesting.vestedAmount(this.token.address); + const vestedPost = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); vestedPre.should.bignumber.equal(vestedPost); }); it('should fail to be revoked a second time', async function () { - await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - - await this.vesting.vestedAmount(this.token.address); - await this.vesting.revoke(this.token.address, { from: owner }); - await shouldFail.reverting(this.vesting.revoke(this.token.address, { from: owner })); }); + + function vestedAmount (total, now, start, cliffDuration, duration) { + return (now < start + cliffDuration) ? 0 : Math.round(total * (now - start) / duration); + } }); }); From 96d6103e0b70c5a09005bc77cf5bb9310fb90ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:47:35 -0300 Subject: [PATCH 062/205] Made some inherit-only contracts internal. (#1433) * Made some inherit-only contracts internal. * Added OwnableMock. --- contracts/access/roles/CapperRole.sol | 2 +- contracts/access/roles/MinterRole.sol | 2 +- contracts/access/roles/PauserRole.sol | 2 +- contracts/access/roles/SignerRole.sol | 2 +- contracts/drafts/SignatureBouncer.sol | 2 ++ contracts/introspection/ERC165.sol | 2 +- contracts/lifecycle/Pausable.sol | 2 +- contracts/mocks/OwnableMock.sol | 6 ++++++ contracts/ownership/Ownable.sol | 2 +- contracts/ownership/Secondary.sol | 2 +- contracts/payment/PullPayment.sol | 2 +- contracts/utils/ReentrancyGuard.sol | 2 +- test/ownership/Ownable.test.js | 2 +- 13 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 contracts/mocks/OwnableMock.sol diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index a79e8e694..d6b2ba066 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -10,7 +10,7 @@ contract CapperRole { Roles.Role private cappers; - constructor() public { + constructor() internal { _addCapper(msg.sender); } diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index d908e3004..57f4a5a80 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -10,7 +10,7 @@ contract MinterRole { Roles.Role private minters; - constructor() public { + constructor() internal { _addMinter(msg.sender); } diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index d59839d6b..58bb6a313 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -10,7 +10,7 @@ contract PauserRole { Roles.Role private pausers; - constructor() public { + constructor() internal { _addPauser(msg.sender); } diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index bbf8fd36f..6a2bc602d 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -10,7 +10,7 @@ contract SignerRole { Roles.Role private signers; - constructor() public { + constructor() internal { _addSigner(msg.sender); } diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index ff596b006..4327a2bbe 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -36,6 +36,8 @@ contract SignatureBouncer is SignerRole { // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes uint256 private constant _SIGNATURE_SIZE = 96; + constructor() internal {} + /** * @dev requires that a valid signature of a signer was provided */ diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 60bcd53f3..5d083acdf 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -25,7 +25,7 @@ contract ERC165 is IERC165 { * implement ERC165 itself */ constructor() - public + internal { _registerInterface(_InterfaceId_ERC165); } diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index a6cae2a55..0e7feb780 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -12,7 +12,7 @@ contract Pausable is PauserRole { bool private _paused; - constructor() public { + constructor() internal { _paused = false; } diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol new file mode 100644 index 000000000..e16a89012 --- /dev/null +++ b/contracts/mocks/OwnableMock.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.4.24; + +import "../ownership/Ownable.sol"; + +contract OwnableMock is Ownable { +} diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 5279d5d42..7b5b72102 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -17,7 +17,7 @@ contract Ownable { * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - constructor() public { + constructor() internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index d602d67ec..02d2982a3 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -10,7 +10,7 @@ contract Secondary { /** * @dev Sets the primary account to the one that is creating the Secondary contract. */ - constructor() public { + constructor() internal { _primary = msg.sender; } diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 4db11c089..f6d7e2c1e 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -10,7 +10,7 @@ import "./escrow/Escrow.sol"; contract PullPayment { Escrow private _escrow; - constructor() public { + constructor() internal { _escrow = new Escrow(); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 4c10dc775..368f2720f 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -11,7 +11,7 @@ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; - constructor() public { + constructor() internal { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; diff --git a/test/ownership/Ownable.test.js b/test/ownership/Ownable.test.js index 9b9c1bf3e..6f8a813e5 100644 --- a/test/ownership/Ownable.test.js +++ b/test/ownership/Ownable.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeOwnable } = require('./Ownable.behavior'); -const Ownable = artifacts.require('Ownable'); +const Ownable = artifacts.require('OwnableMock'); contract('Ownable', function ([_, owner, ...otherAccounts]) { beforeEach(async function () { From ff0c048ad9fb24b1cb36fe43a0aae9010a87de77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:47:55 -0300 Subject: [PATCH 063/205] Added replay attack notice to SignatureBouncer. (#1434) --- contracts/drafts/SignatureBouncer.sol | 37 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index 4327a2bbe..2cd600b35 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -6,26 +6,33 @@ import "../cryptography/ECDSA.sol"; /** * @title SignatureBouncer * @author PhABC, Shrugs and aflesher - * @dev SignatureBouncer allows users to submit a signature as a permission to do an action. - * If the signature is from one of the authorized signer addresses, the signature - * is valid. + * @dev SignatureBouncer allows users to submit a signature as a permission to + * do an action. + * If the signature is from one of the authorized signer addresses, the + * signature is valid. + * Note that SignatureBouncer offers no protection against replay attacks, users + * must add this themselves! + * * Signer addresses can be individual servers signing grants or different - * users within a decentralized club that have permission to invite other members. - * This technique is useful for whitelists and airdrops; instead of putting all - * valid addresses on-chain, simply sign a grant of the form - * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid signer address. + * users within a decentralized club that have permission to invite other + * members. This technique is useful for whitelists and airdrops; instead of + * putting all valid addresses on-chain, simply sign a grant of the form + * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a + * valid signer address. * Then restrict access to your crowdsale/whitelist/airdrop using the * `onlyValidSignature` modifier (or implement your own using _isValidSignature). * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and - * `onlyValidSignatureAndData` can be used to restrict access to only a given method - * or a given method with given parameters respectively. + * `onlyValidSignatureAndData` can be used to restrict access to only a given + * method or a given method with given parameters respectively. * See the tests in SignatureBouncer.test.js for specific usage examples. - * @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _signature - * parameter the "last" parameter. You cannot sign a message that has its own - * signature in it so the last 128 bytes of msg.data (which represents the - * length of the _signature data and the _signaature data itself) is ignored when validating. - * Also non fixed sized parameters make constructing the data in the signature - * much more complex. See https://ethereum.stackexchange.com/a/50616 for more details. + * + * @notice A method that uses the `onlyValidSignatureAndData` modifier must make + * the _signature parameter the "last" parameter. You cannot sign a message that + * has its own signature in it so the last 128 bytes of msg.data (which + * represents the length of the _signature data and the _signaature data itself) + * is ignored when validating. Also non fixed sized parameters make constructing + * the data in the signature much more complex. + * See https://ethereum.stackexchange.com/a/50616 for more details. */ contract SignatureBouncer is SignerRole { using ECDSA for bytes32; From 0231fac51482b874621169351b9adaec51bd7ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:49:01 -0300 Subject: [PATCH 064/205] Added leading underscore to internal functions, renamed supportsInterfaces. (#1435) --- contracts/introspection/ERC165Checker.sol | 24 +++++++++---------- contracts/mocks/ERC165CheckerMock.sol | 8 +++---- test/introspection/ERC165Checker.test.js | 28 +++++++++++------------ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 3491df904..2490b191e 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -20,15 +20,15 @@ library ERC165Checker { * @param account The address of the contract to query for support of ERC165 * @return true if the contract at account implements ERC165 */ - function supportsERC165(address account) + function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return supportsERC165Interface(account, _InterfaceId_ERC165) && - !supportsERC165Interface(account, _InterfaceId_Invalid); + return _supportsERC165Interface(account, _InterfaceId_ERC165) && + !_supportsERC165Interface(account, _InterfaceId_Invalid); } /** @@ -39,14 +39,14 @@ library ERC165Checker { * identifier interfaceId, false otherwise * @dev Interface identification is specified in ERC-165. */ - function supportsInterface(address account, bytes4 interfaceId) + function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId - return supportsERC165(account) && - supportsERC165Interface(account, interfaceId); + return _supportsERC165(account) && + _supportsERC165Interface(account, interfaceId); } /** @@ -57,19 +57,19 @@ library ERC165Checker { * interfaceIds list, false otherwise * @dev Interface identification is specified in ERC-165. */ - function supportsInterfaces(address account, bytes4[] interfaceIds) + function _supportsAllInterfaces(address account, bytes4[] interfaceIds) internal view returns (bool) { // query support of ERC165 itself - if (!supportsERC165(account)) { + if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { - if (!supportsERC165Interface(account, interfaceIds[i])) { + if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } @@ -89,14 +89,14 @@ library ERC165Checker { * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ - function supportsERC165Interface(address account, bytes4 interfaceId) + function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId - (bool success, bool result) = callERC165SupportsInterface( + (bool success, bool result) = _callERC165SupportsInterface( account, interfaceId); return (success && result); @@ -110,7 +110,7 @@ library ERC165Checker { * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ - function callERC165SupportsInterface( + function _callERC165SupportsInterface( address account, bytes4 interfaceId ) diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index b0728ba15..559cea0d7 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -10,7 +10,7 @@ contract ERC165CheckerMock { view returns (bool) { - return account.supportsERC165(); + return account._supportsERC165(); } function supportsInterface(address account, bytes4 interfaceId) @@ -18,14 +18,14 @@ contract ERC165CheckerMock { view returns (bool) { - return account.supportsInterface(interfaceId); + return account._supportsInterface(interfaceId); } - function supportsInterfaces(address account, bytes4[] interfaceIds) + function supportsAllInterfaces(address account, bytes4[] interfaceIds) public view returns (bool) { - return account.supportsInterfaces(interfaceIds); + return account._supportsAllInterfaces(interfaceIds); } } diff --git a/test/introspection/ERC165Checker.test.js b/test/introspection/ERC165Checker.test.js index a6bfc518d..7f5dc9fc5 100644 --- a/test/introspection/ERC165Checker.test.js +++ b/test/introspection/ERC165Checker.test.js @@ -32,8 +32,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(false); }); }); @@ -53,8 +53,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(false); }); }); @@ -74,8 +74,8 @@ contract('ERC165Checker', function () { supported.should.equal(true); }); - it('supports mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('supports mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(true); }); }); @@ -98,22 +98,22 @@ contract('ERC165Checker', function () { }; }); - it('supports all interfaceIds via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, this.supportedInterfaces); + it('supports all interfaceIds via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, this.supportedInterfaces); supported.should.equal(true); }); - it('supports none of the interfaces queried via supportsInterfaces', async function () { + it('supports none of the interfaces queried via supportsAllInterfaces', async function () { const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2]; - const supported = await this.mock.supportsInterfaces(this.target.address, interfaceIdsToTest); + const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest); supported.should.equal(false); }); - it('supports not all of the interfaces queried via supportsInterfaces', async function () { + it('supports not all of the interfaces queried via supportsAllInterfaces', async function () { const interfaceIdsToTest = [...this.supportedInterfaces, DUMMY_UNSUPPORTED_ID]; - const supported = await this.mock.supportsInterfaces(this.target.address, interfaceIdsToTest); + const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest); supported.should.equal(false); }); }); @@ -129,8 +129,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]); supported.should.equal(false); }); }); From cbe414864fc74290ae1c08175a4b1f7b59941bbc Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 18 Oct 2018 19:30:33 +0530 Subject: [PATCH 065/205] Events added to Secondary (#1425) * Update contracts/ownership/Secondary.sol * Update Secondary.sol * Update Secondary.test.js * Update Secondary.test.js * Update Secondary.sol --- contracts/ownership/Secondary.sol | 16 ++++++++++++++-- test/ownership/Secondary.test.js | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index 02d2982a3..67d2250d5 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -7,11 +7,16 @@ pragma solidity ^0.4.24; contract Secondary { address private _primary; + event PrimaryTransferred( + address recipient + ); + /** * @dev Sets the primary account to the one that is creating the Secondary contract. */ constructor() internal { _primary = msg.sender; + emit PrimaryTransferred(_primary); } /** @@ -22,13 +27,20 @@ contract Secondary { _; } + /** + * @return the address of the primary. + */ function primary() public view returns (address) { return _primary; } - + + /** + * @dev Transfers contract to a new primary. + * @param recipient The address of new primary. + */ function transferPrimary(address recipient) public onlyPrimary { require(recipient != address(0)); - _primary = recipient; + emit PrimaryTransferred(_primary); } } diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 55283963b..c8772db1f 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,4 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); +const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); const SecondaryMock = artifacts.require('SecondaryMock'); @@ -27,7 +28,8 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { describe('transferPrimary', function () { it('makes the recipient the new primary', async function () { - await this.secondary.transferPrimary(newPrimary, { from: primary }); + const { logs } = await this.secondary.transferPrimary(newPrimary, { from: primary }); + expectEvent.inLogs(logs, 'PrimaryTransferred', { recipient: newPrimary }); (await this.secondary.primary()).should.equal(newPrimary); }); From fcab9c89f25376227399914a6e4b8e89ee3b21d3 Mon Sep 17 00:00:00 2001 From: Christopher Glisch Date: Thu, 18 Oct 2018 10:26:39 -0400 Subject: [PATCH 066/205] Added address of pauser/unpauser in events (#1410) * Added address of pauser/unpauser in events * Added the account to the Pausable tests. --- contracts/lifecycle/Pausable.sol | 8 ++++---- test/lifecycle/Pausable.test.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 0e7feb780..3703fed4b 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -7,8 +7,8 @@ import "../access/roles/PauserRole.sol"; * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is PauserRole { - event Paused(); - event Unpaused(); + event Paused(address account); + event Unpaused(address account); bool private _paused; @@ -44,7 +44,7 @@ contract Pausable is PauserRole { */ function pause() public onlyPauser whenNotPaused { _paused = true; - emit Paused(); + emit Paused(msg.sender); } /** @@ -52,6 +52,6 @@ contract Pausable is PauserRole { */ function unpause() public onlyPauser whenPaused { _paused = false; - emit Unpaused(); + emit Unpaused(msg.sender); } } diff --git a/test/lifecycle/Pausable.test.js b/test/lifecycle/Pausable.test.js index a7f6d637d..f279e09a7 100644 --- a/test/lifecycle/Pausable.test.js +++ b/test/lifecycle/Pausable.test.js @@ -57,7 +57,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('emits a Paused event', function () { - expectEvent.inLogs(this.logs, 'Paused'); + expectEvent.inLogs(this.logs, 'Paused', { account: pauser }); }); it('cannot perform normal process in pause', async function () { @@ -89,7 +89,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('emits an Unpaused event', function () { - expectEvent.inLogs(this.logs, 'Unpaused'); + expectEvent.inLogs(this.logs, 'Unpaused', { account: pauser }); }); it('should resume allowing normal process', async function () { From a07499796af0a00bf12283f5591f934843a1fbc2 Mon Sep 17 00:00:00 2001 From: cardmaniac992 <44122792+cardmaniac992@users.noreply.github.com> Date: Thu, 18 Oct 2018 16:26:54 +0200 Subject: [PATCH 067/205] SplitPayment improvements (#1417) * Renamed file, added events and set _addPayee to private * unwanted file * adjusted test * adjusted test * PaymentReceived event added * Added event testing. * Fix static tests --- .../{SplitPayment.sol => PaymentSplitter.sol} | 16 ++++++++--- ...ayment.test.js => PaymentSplitter.test.js} | 28 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) rename contracts/payment/{SplitPayment.sol => PaymentSplitter.sol} (84%) rename test/payment/{SplitPayment.test.js => PaymentSplitter.test.js} (73%) diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/PaymentSplitter.sol similarity index 84% rename from contracts/payment/SplitPayment.sol rename to contracts/payment/PaymentSplitter.sol index 960772182..0a1b470ef 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/PaymentSplitter.sol @@ -3,13 +3,17 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; /** - * @title SplitPayment + * @title PaymentSplitter * @dev This contract can be used when payments need to be received by a group * of people and split proportionately to some number of shares they own. */ -contract SplitPayment { +contract PaymentSplitter { using SafeMath for uint256; + event PayeeAdded(address account, uint256 shares); + event PaymentReleased(address to, uint256 amount); + event PaymentReceived(address from, uint256 amount); + uint256 private _totalShares; uint256 private _totalReleased; @@ -32,7 +36,9 @@ contract SplitPayment { /** * @dev payable fallback */ - function () external payable {} + function () external payable { + emit PaymentReceived(msg.sender, msg.value); + } /** * @return the total shares of the contract. @@ -89,6 +95,7 @@ contract SplitPayment { _totalReleased = _totalReleased.add(payment); account.transfer(payment); + emit PaymentReleased(account, payment); } /** @@ -96,7 +103,7 @@ contract SplitPayment { * @param account The address of the payee to add. * @param shares_ The number of shares owned by the payee. */ - function _addPayee(address account, uint256 shares_) internal { + function _addPayee(address account, uint256 shares_) private { require(account != address(0)); require(shares_ > 0); require(_shares[account] == 0); @@ -104,5 +111,6 @@ contract SplitPayment { _payees.push(account); _shares[account] = shares_; _totalShares = _totalShares.add(shares_); + emit PayeeAdded(account, shares_); } } diff --git a/test/payment/SplitPayment.test.js b/test/payment/PaymentSplitter.test.js similarity index 73% rename from test/payment/SplitPayment.test.js rename to test/payment/PaymentSplitter.test.js index 6a10a5131..60e5654dc 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/PaymentSplitter.test.js @@ -1,4 +1,5 @@ const { ethGetBalance } = require('../helpers/web3'); +const expectEvent = require('../helpers/expectEvent'); const { sendEther } = require('./../helpers/sendTransaction'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('./../helpers/constants'); @@ -10,33 +11,33 @@ require('chai') .should(); const shouldFail = require('../helpers/shouldFail'); -const SplitPayment = artifacts.require('SplitPayment'); +const PaymentSplitter = artifacts.require('PaymentSplitter'); -contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { +contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { const amount = ether(1.0); it('rejects an empty set of payees', async function () { - await shouldFail.reverting(SplitPayment.new([], [])); + await shouldFail.reverting(PaymentSplitter.new([], [])); }); it('rejects more payees than shares', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2, payee3], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2, payee3], [20, 30])); }); it('rejects more shares than payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 30, 40])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 30, 40])); }); it('rejects null payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, ZERO_ADDRESS], [20, 30])); }); it('rejects zero-valued shares', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 0])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 0])); }); it('rejects repeated payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee1], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee1], [20, 30])); }); context('once deployed', function () { @@ -44,7 +45,7 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, this.payees = [payee1, payee2, payee3]; this.shares = [20, 10, 70]; - this.contract = await SplitPayment.new(this.payees, this.shares); + this.contract = await PaymentSplitter.new(this.payees, this.shares); }); it('should have total shares', async function () { @@ -90,19 +91,22 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, // distribute to payees const initAmount1 = await ethGetBalance(payee1); - await this.contract.release(payee1); + const { logs: logs1 } = await this.contract.release(payee1); const profit1 = (await ethGetBalance(payee1)).sub(initAmount1); profit1.sub(web3.toWei(0.20, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs1, 'PaymentReleased', { to: payee1, amount: profit1 }); const initAmount2 = await ethGetBalance(payee2); - await this.contract.release(payee2); + const { logs: logs2 } = await this.contract.release(payee2); const profit2 = (await ethGetBalance(payee2)).sub(initAmount2); profit2.sub(web3.toWei(0.10, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs2, 'PaymentReleased', { to: payee2, amount: profit2 }); const initAmount3 = await ethGetBalance(payee3); - await this.contract.release(payee3); + const { logs: logs3 } = await this.contract.release(payee3); const profit3 = (await ethGetBalance(payee3)).sub(initAmount3); profit3.sub(web3.toWei(0.70, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs3, 'PaymentReleased', { to: payee3, amount: profit3 }); // end balance should be zero (await ethGetBalance(this.contract.address)).should.be.bignumber.equal(0); From 67dac7ae9960fd1790671a315cde56c901db5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 11:27:46 -0300 Subject: [PATCH 068/205] TokenVesting improvements (#1431) * Improved TokenVesting events. * Added extra checks to TokenVesting. * Renamed the events. * Fixed linter error. * Fixed a test that failed to cover a require. * Renamed TokensRevoked to TokenVestingRevoked. --- contracts/drafts/TokenVesting.sol | 10 ++++++---- test/drafts/TokenVesting.test.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 965ace102..2f5fd2fdc 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -16,8 +16,8 @@ contract TokenVesting is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; - event Released(uint256 amount); - event Revoked(); + event TokensReleased(address token, uint256 amount); + event TokenVestingRevoked(address token); // beneficiary of tokens after they are released address private _beneficiary; @@ -52,6 +52,8 @@ contract TokenVesting is Ownable { { require(beneficiary != address(0)); require(cliffDuration <= duration); + require(duration > 0); + require(start.add(duration) > block.timestamp); _beneficiary = beneficiary; _revocable = revocable; @@ -122,7 +124,7 @@ contract TokenVesting is Ownable { token.safeTransfer(_beneficiary, unreleased); - emit Released(unreleased); + emit TokensReleased(token, unreleased); } /** @@ -143,7 +145,7 @@ contract TokenVesting is Ownable { token.safeTransfer(owner(), refund); - emit Revoked(); + emit TokenVestingRevoked(token); } /** diff --git a/test/drafts/TokenVesting.test.js b/test/drafts/TokenVesting.test.js index c43a0d8b8..be872ae22 100644 --- a/test/drafts/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -1,4 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); +const expectEvent = require('../helpers/expectEvent'); const time = require('../helpers/time'); const { ethGetBlock } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -22,7 +23,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { this.duration = time.duration.years(2); }); - it('rejects a duration shorter than the cliff', async function () { + it('reverts with a duration shorter than the cliff', async function () { const cliffDuration = this.duration; const duration = this.cliffDuration; @@ -33,12 +34,28 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ); }); - it('requires a valid beneficiary', async function () { + it('reverts with a null beneficiary', async function () { await shouldFail.reverting( TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }) ); }); + it('reverts with a null duration', async function () { + // cliffDuration should also be 0, since the duration must be larger than the cliff + await shouldFail.reverting( + TokenVesting.new(beneficiary, this.start, 0, 0, true, { from: owner }) + ); + }); + + it('reverts if the end time is in the past', async function () { + const now = await time.latest(); + + this.start = now - this.duration - time.duration.minutes(1); + await shouldFail.reverting( + TokenVesting.new(beneficiary, this.start, this.cliffDuration, this.duration, true, { from: owner }) + ); + }); + context('once deployed', function () { beforeEach(async function () { this.vesting = await TokenVesting.new( @@ -62,7 +79,11 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('can be released after cliff', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(1)); - await this.vesting.release(this.token.address); + const { logs } = await this.vesting.release(this.token.address); + expectEvent.inLogs(logs, 'TokensReleased', { + token: this.token.address, + amount: await this.token.balanceOf(beneficiary), + }); }); it('should release proper amount after cliff', async function () { @@ -100,7 +121,8 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should be revoked by owner if revocable is set', async function () { - await this.vesting.revoke(this.token.address, { from: owner }); + const { logs } = await this.vesting.revoke(this.token.address, { from: owner }); + expectEvent.inLogs(logs, 'TokenVestingRevoked', { token: this.token.address }); (await this.vesting.revoked(this.token.address)).should.equal(true); }); From 315f426f5c2db7953b977bbf605b5d796636cd97 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 18 Oct 2018 20:55:03 +0530 Subject: [PATCH 069/205] Improved SafeERC20 allowance handling (#1407) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * allowance methods in library * Improved SafeERC20 tests. * Fixed test coverage. --- contracts/mocks/SafeERC20Helper.sol | 58 +++++++++++++------ contracts/token/ERC20/SafeERC20.sol | 29 ++++++++++ test/token/ERC20/SafeERC20.test.js | 90 ++++++++++++++++++++++++----- 3 files changed, 142 insertions(+), 35 deletions(-) diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index c80c762d9..7e639f86f 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -3,10 +3,8 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; -contract ERC20FailingMock is IERC20 { - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20FailingMock { + uint256 private _allowance; function transfer(address, uint256) public returns (bool) { return false; @@ -20,19 +18,13 @@ contract ERC20FailingMock is IERC20 { return false; } - function balanceOf(address) public view returns (uint256) { - return 0; - } - function allowance(address, address) public view returns (uint256) { return 0; } } -contract ERC20SucceedingMock is IERC20 { - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20SucceedingMock { + uint256 private _allowance; function transfer(address, uint256) public returns (bool) { return true; @@ -46,12 +38,12 @@ contract ERC20SucceedingMock is IERC20 { return true; } - function balanceOf(address) public view returns (uint256) { - return 0; + function setAllowance(uint256 allowance_) public { + _allowance = allowance_; } function allowance(address, address) public view returns (uint256) { - return 0; + return _allowance; } } @@ -62,10 +54,12 @@ contract SafeERC20Helper { IERC20 private _succeeding; constructor() public { - _failing = new ERC20FailingMock(); - _succeeding = new ERC20SucceedingMock(); + _failing = IERC20(new ERC20FailingMock()); + _succeeding = IERC20(new ERC20SucceedingMock()); } + // Using _failing + function doFailingTransfer() public { _failing.safeTransfer(address(0), 0); } @@ -78,6 +72,16 @@ contract SafeERC20Helper { _failing.safeApprove(address(0), 0); } + function doFailingIncreaseAllowance() public { + _failing.safeIncreaseAllowance(address(0), 0); + } + + function doFailingDecreaseAllowance() public { + _failing.safeDecreaseAllowance(address(0), 0); + } + + // Using _succeeding + function doSucceedingTransfer() public { _succeeding.safeTransfer(address(0), 0); } @@ -86,7 +90,23 @@ contract SafeERC20Helper { _succeeding.safeTransferFrom(address(0), address(0), 0); } - function doSucceedingApprove() public { - _succeeding.safeApprove(address(0), 0); + function doSucceedingApprove(uint256 amount) public { + _succeeding.safeApprove(address(0), amount); + } + + function doSucceedingIncreaseAllowance(uint256 amount) public { + _succeeding.safeIncreaseAllowance(address(0), amount); + } + + function doSucceedingDecreaseAllowance(uint256 amount) public { + _succeeding.safeDecreaseAllowance(address(0), amount); + } + + function setAllowance(uint256 allowance_) public { + ERC20SucceedingMock(_succeeding).setAllowance(allowance_); + } + + function allowance() public view returns (uint256) { + return _succeeding.allowance(address(0), address(0)); } } diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 10c6ff2bc..9e6bf6a20 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -10,6 +10,9 @@ import "./IERC20.sol"; * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { + + using SafeMath for uint256; + function safeTransfer( IERC20 token, address to, @@ -38,6 +41,32 @@ library SafeERC20 { ) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require((value == 0) || (token.allowance(msg.sender, spender) == 0)); require(token.approve(spender, value)); } + + function safeIncreaseAllowance( + IERC20 token, + address spender, + uint256 value + ) + internal + { + uint256 newAllowance = token.allowance(address(this), spender).add(value); + require(token.approve(spender, newAllowance)); + } + + function safeDecreaseAllowance( + IERC20 token, + address spender, + uint256 value + ) + internal + { + uint256 newAllowance = token.allowance(address(this), spender).sub(value); + require(token.approve(spender, newAllowance)); + } } diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index b6c87554b..c8dea7382 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -10,27 +10,85 @@ contract('SafeERC20', function () { this.helper = await SafeERC20Helper.new(); }); - it('should throw on failed transfer', async function () { - await shouldFail.reverting(this.helper.doFailingTransfer()); + describe('with token that returns false on all calls', function () { + it('reverts on transfer', async function () { + await shouldFail.reverting(this.helper.doFailingTransfer()); + }); + + it('reverts on transferFrom', async function () { + await shouldFail.reverting(this.helper.doFailingTransferFrom()); + }); + + it('reverts on approve', async function () { + await shouldFail.reverting(this.helper.doFailingApprove()); + }); + + it('reverts on increaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingIncreaseAllowance()); + }); + + it('reverts on decreaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingDecreaseAllowance()); + }); }); - it('should throw on failed transferFrom', async function () { - await shouldFail.reverting(this.helper.doFailingTransferFrom()); - }); + describe('with token that returns true on all calls', function () { + it('doesn\'t revert on transfer', async function () { + await this.helper.doSucceedingTransfer(); + }); - it('should throw on failed approve', async function () { - await shouldFail.reverting(this.helper.doFailingApprove()); - }); + it('doesn\'t revert on transferFrom', async function () { + await this.helper.doSucceedingTransferFrom(); + }); - it('should not throw on succeeding transfer', async function () { - await this.helper.doSucceedingTransfer(); - }); + describe('approvals', function () { + context('with zero allowance', function () { + beforeEach(async function () { + await this.helper.setAllowance(0); + }); - it('should not throw on succeeding transferFrom', async function () { - await this.helper.doSucceedingTransferFrom(); - }); + it('doesn\'t revert when approving a non-zero allowance', async function () { + await this.helper.doSucceedingApprove(100); + }); - it('should not throw on succeeding approve', async function () { - await this.helper.doSucceedingApprove(); + it('doesn\'t revert when approving a zero allowance', async function () { + await this.helper.doSucceedingApprove(0); + }); + + it('doesn\'t revert when increasing the allowance', async function () { + await this.helper.doSucceedingIncreaseAllowance(10); + }); + + it('reverts when decreasing the allowance', async function () { + await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(10)); + }); + }); + + context('with non-zero allowance', function () { + beforeEach(async function () { + await this.helper.setAllowance(100); + }); + + it('reverts when approving a non-zero allowance', async function () { + await shouldFail.reverting(this.helper.doSucceedingApprove(20)); + }); + + it('doesn\'t revert when approving a zero allowance', async function () { + await this.helper.doSucceedingApprove(0); + }); + + it('doesn\'t revert when increasing the allowance', async function () { + await this.helper.doSucceedingIncreaseAllowance(10); + }); + + it('doesn\'t revert when decreasing the allowance to a positive value', async function () { + await this.helper.doSucceedingDecreaseAllowance(50); + }); + + it('reverts when decreasing the allowance to a negative value', async function () { + await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(200)); + }); + }); + }); }); }); From d9fdffe88e8474f5d0cd469d0c14714bf436f34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:35:57 -0300 Subject: [PATCH 070/205] Internal crowdsales (#1439) * Made some internal crowdsale methods internal. * Made all Crowdsale constructors internal. --- contracts/crowdsale/Crowdsale.sol | 4 +++- .../crowdsale/distribution/FinalizableCrowdsale.sol | 2 +- .../crowdsale/distribution/PostDeliveryCrowdsale.sol | 2 ++ contracts/crowdsale/distribution/RefundableCrowdsale.sol | 2 +- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 2 +- contracts/crowdsale/emission/MintedCrowdsale.sol | 1 + contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 2 +- contracts/crowdsale/validation/CappedCrowdsale.sol | 3 ++- .../crowdsale/validation/IndividuallyCappedCrowdsale.sol | 3 +++ contracts/crowdsale/validation/TimedCrowdsale.sol | 3 ++- contracts/mocks/CrowdsaleMock.sol | 9 +++++++++ test/crowdsale/Crowdsale.test.js | 2 +- 12 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 contracts/mocks/CrowdsaleMock.sol diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index c1302ede4..f425718fd 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -57,7 +57,7 @@ contract Crowdsale { * @param wallet Address where collected funds will be forwarded to * @param token Address of the token being sold */ - constructor(uint256 rate, address wallet, IERC20 token) public { + constructor(uint256 rate, address wallet, IERC20 token) internal { require(rate > 0); require(wallet != address(0)); require(token != address(0)); @@ -152,6 +152,7 @@ contract Crowdsale { uint256 weiAmount ) internal + view { require(beneficiary != address(0)); require(weiAmount != 0); @@ -167,6 +168,7 @@ contract Crowdsale { uint256 weiAmount ) internal + view { // optional override } diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index a640dca83..bcdfa4563 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -15,7 +15,7 @@ contract FinalizableCrowdsale is TimedCrowdsale { event CrowdsaleFinalized(); - constructor() public { + constructor() internal { _finalized = false; } diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index da9392aed..ca05f6d66 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -13,6 +13,8 @@ contract PostDeliveryCrowdsale is TimedCrowdsale { mapping(address => uint256) private _balances; + constructor() internal {} + /** * @dev Withdraw tokens only after crowdsale ends. * @param beneficiary Whose tokens will be withdrawn. diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index d55a573fb..d670f9ced 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -22,7 +22,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale { * @dev Constructor, creates RefundEscrow. * @param goal Funding goal */ - constructor(uint256 goal) public { + constructor(uint256 goal) internal { require(goal > 0); _escrow = new RefundEscrow(wallet()); _goal = goal; diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index 736635e0b..ec9918feb 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -19,7 +19,7 @@ contract AllowanceCrowdsale is Crowdsale { * @dev Constructor, takes token wallet address. * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale */ - constructor(address tokenWallet) public { + constructor(address tokenWallet) internal { require(tokenWallet != address(0)); _tokenWallet = tokenWallet; } diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index 62b03189a..3ebea857d 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -9,6 +9,7 @@ import "../../token/ERC20/ERC20Mintable.sol"; * Token ownership should be transferred to MintedCrowdsale for minting. */ contract MintedCrowdsale is Crowdsale { + constructor() internal {} /** * @dev Overrides delivery by minting tokens upon purchase. diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 386c6202b..70189a168 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -20,7 +20,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { * @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale */ - constructor(uint256 initialRate, uint256 finalRate) public { + constructor(uint256 initialRate, uint256 finalRate) internal { require(finalRate > 0); require(initialRate >= finalRate); _initialRate = initialRate; diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 21708c34a..4d9eb604d 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -16,7 +16,7 @@ contract CappedCrowdsale is Crowdsale { * @dev Constructor, takes maximum amount of wei accepted in the crowdsale. * @param cap Max amount of wei to be contributed */ - constructor(uint256 cap) public { + constructor(uint256 cap) internal { require(cap > 0); _cap = cap; } @@ -46,6 +46,7 @@ contract CappedCrowdsale is Crowdsale { uint256 weiAmount ) internal + view { super._preValidatePurchase(beneficiary, weiAmount); require(weiRaised().add(weiAmount) <= _cap); diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index d00cb602e..5a5d4e317 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -14,6 +14,8 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { mapping(address => uint256) private _contributions; mapping(address => uint256) private _caps; + constructor() internal {} + /** * @dev Sets a specific beneficiary's maximum contribution. * @param beneficiary Address to be capped @@ -53,6 +55,7 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { uint256 weiAmount ) internal + view { super._preValidatePurchase(beneficiary, weiAmount); require( diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index 098112cae..d39242578 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -26,7 +26,7 @@ contract TimedCrowdsale is Crowdsale { * @param openingTime Crowdsale opening time * @param closingTime Crowdsale closing time */ - constructor(uint256 openingTime, uint256 closingTime) public { + constructor(uint256 openingTime, uint256 closingTime) internal { // solium-disable-next-line security/no-block-members require(openingTime >= block.timestamp); require(closingTime >= openingTime); @@ -77,6 +77,7 @@ contract TimedCrowdsale is Crowdsale { ) internal onlyWhileOpen + view { super._preValidatePurchase(beneficiary, weiAmount); } diff --git a/contracts/mocks/CrowdsaleMock.sol b/contracts/mocks/CrowdsaleMock.sol new file mode 100644 index 000000000..834105e6a --- /dev/null +++ b/contracts/mocks/CrowdsaleMock.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.24; + +import "../crowdsale/Crowdsale.sol"; + +contract CrowdsaleMock is Crowdsale { + constructor(uint256 rate, address wallet, IERC20 token) public + Crowdsale(rate, wallet, token) { + } +} diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 8875e9157..b7528e4e9 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -10,7 +10,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const Crowdsale = artifacts.require('Crowdsale'); +const Crowdsale = artifacts.require('CrowdsaleMock'); const SimpleToken = artifacts.require('SimpleToken'); contract('Crowdsale', function ([_, investor, wallet, purchaser]) { From 1c5f16ae2659c3c158baebff077cc414fd9c5991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:36:11 -0300 Subject: [PATCH 071/205] Closing time must be strictly after opening time. (#1440) --- contracts/crowdsale/validation/TimedCrowdsale.sol | 2 +- test/crowdsale/TimedCrowdsale.test.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index d39242578..73d6a5c0f 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -29,7 +29,7 @@ contract TimedCrowdsale is Crowdsale { constructor(uint256 openingTime, uint256 closingTime) internal { // solium-disable-next-line security/no-block-members require(openingTime >= block.timestamp); - require(closingTime >= openingTime); + require(closingTime > openingTime); _openingTime = openingTime; _closingTime = closingTime; diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index eb2a9bf51..5b0b457b7 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -29,18 +29,24 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { this.token = await SimpleToken.new(); }); - it('rejects an opening time in the past', async function () { + it('reverts if the opening time is in the past', async function () { await shouldFail.reverting(TimedCrowdsaleImpl.new( (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address )); }); - it('rejects a closing time before the opening time', async function () { + it('reverts if the closing time is before the opening time', async function () { await shouldFail.reverting(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address )); }); + it('reverts if the closing time equals the opening time', async function () { + await shouldFail.reverting(TimedCrowdsaleImpl.new( + this.openingTime, this.openingTime, rate, wallet, this.token.address + )); + }); + context('with crowdsale', function () { beforeEach(async function () { this.crowdsale = await TimedCrowdsaleImpl.new( From 9155bfe27f2ad2423e5ec5d4205cc42cc4aba566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:36:27 -0300 Subject: [PATCH 072/205] IncPriceCrowdsale consistently returns 0 outside of the crowdsale window. (#1442) --- contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 4 ++++ test/crowdsale/IncreasingPriceCrowdsale.test.js | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 70189a168..4d2b44931 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -47,6 +47,10 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { * @return The number of tokens a buyer gets per wei at a given time */ function getCurrentRate() public view returns (uint256) { + if (!isOpen()) { + return 0; + } + // solium-disable-next-line security/no-block-members uint256 elapsedTime = block.timestamp.sub(openingTime()); uint256 timeRange = closingTime().sub(openingTime()); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index a76186bbc..51946b5ee 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -59,6 +59,15 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) (await this.crowdsale.finalRate()).should.be.bignumber.equal(finalRate); }); + it('returns a rate of 0 before the crowdsale starts', async function () { + (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); + }); + + it('returns a rate of 0 after the crowdsale ends', async function () { + await time.increaseTo(this.afterClosingTime); + (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); + }); + it('at start', async function () { await time.increaseTo(this.startTime); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); From c8220aeea8e194de2a9c8e8daaa574f5e1e033f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:49:31 -0300 Subject: [PATCH 073/205] ERC20Capped now capps _all_ minting, even internal calls. (#1443) --- contracts/token/ERC20/ERC20Capped.sol | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 9f3ea8bfc..a80dd491c 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -24,22 +24,8 @@ contract ERC20Capped is ERC20Mintable { return _cap; } - /** - * @dev Function to mint tokens - * @param to The address that will receive the minted tokens. - * @param value The amount of tokens to mint. - * @return A boolean that indicates if the operation was successful. - */ - function mint( - address to, - uint256 value - ) - public - returns (bool) - { + function _mint(address account, uint256 value) internal { require(totalSupply().add(value) <= _cap); - - return super.mint(to, value); + super._mint(account, value); } - } From 5bf390786291c599601ce1c966971b20d4b6ca54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:49:46 -0300 Subject: [PATCH 074/205] Made tokenURI external, as per the spec. (#1444) --- contracts/token/ERC721/ERC721Metadata.sol | 2 +- contracts/token/ERC721/IERC721Metadata.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 4fb35543c..bd1105188 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -54,7 +54,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ - function tokenURI(uint256 tokenId) public view returns (string) { + function tokenURI(uint256 tokenId) external view returns (string) { require(_exists(tokenId)); return _tokenURIs[tokenId]; } diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index 2e1521208..15b5ae4c6 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -9,5 +9,5 @@ import "./IERC721.sol"; contract IERC721Metadata is IERC721 { function name() external view returns (string); function symbol() external view returns (string); - function tokenURI(uint256 tokenId) public view returns (string); + function tokenURI(uint256 tokenId) external view returns (string); } From 384dff9abeee277f3357b8c472ef38a5ec825df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:56:58 -0300 Subject: [PATCH 075/205] Renamed internal ERC721 check function. (#1445) --- contracts/token/ERC721/ERC721.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index eeee146e2..3dc243874 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -200,7 +200,7 @@ contract ERC721 is ERC165, IERC721 { { transferFrom(from, to, tokenId); // solium-disable-next-line arg-overflow - require(_checkAndCallSafeTransfer(from, to, tokenId, _data)); + require(_checkOnERC721Received(from, to, tokenId, _data)); } /** @@ -306,7 +306,7 @@ contract ERC721 is ERC165, IERC721 { * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ - function _checkAndCallSafeTransfer( + function _checkOnERC721Received( address from, address to, uint256 tokenId, From 94692acb146b4204d7a57b604f160e46dba9c2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:57:16 -0300 Subject: [PATCH 076/205] Crowdsale docs improvements. (#1446) * Added a small Crowdsale fallback gas warning. * Fixed a couple typos. --- contracts/crowdsale/Crowdsale.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index f425718fd..9aa550519 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -73,6 +73,9 @@ contract Crowdsale { /** * @dev fallback function ***DO NOT OVERRIDE*** + * Note that other contracts will transfer fund with a base gas stipend + * of 2300, which is not enough to call buyTokens. Consider calling + * buyTokens directly when purchasing tokens from a contract. */ function () external payable { buyTokens(msg.sender); @@ -100,7 +103,7 @@ contract Crowdsale { } /** - * @return the mount of wei raised. + * @return the amount of wei raised. */ function weiRaised() public view returns (uint256) { return _weiRaised; @@ -108,7 +111,7 @@ contract Crowdsale { /** * @dev low level token purchase ***DO NOT OVERRIDE*** - * @param beneficiary Address performing the token purchase + * @param beneficiary Recipient of the token purchase */ function buyTokens(address beneficiary) public payable { @@ -188,7 +191,7 @@ contract Crowdsale { } /** - * @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens. + * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens. * @param beneficiary Address receiving the tokens * @param tokenAmount Number of tokens to be purchased */ From 5bb865218f02a01d0521c9d9a947cdf4bd32e74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:42:57 -0300 Subject: [PATCH 077/205] Now setting the finalized flag before doing finalization to prevent possbile reentrancy issues. (#1447) --- contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index bcdfa4563..8add165da 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -34,10 +34,10 @@ contract FinalizableCrowdsale is TimedCrowdsale { require(!_finalized); require(hasClosed()); + _finalized = true; + _finalization(); emit CrowdsaleFinalized(); - - _finalized = true; } /** @@ -47,5 +47,4 @@ contract FinalizableCrowdsale is TimedCrowdsale { */ function _finalization() internal { } - } From 28cf567e418b3a653be312c5c70b09e21d5094c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:43:12 -0300 Subject: [PATCH 078/205] Made SampleCrowdsale a bit clearer. (#1448) --- contracts/examples/SampleCrowdsale.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 6e1272223..d22598092 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -4,17 +4,15 @@ import "../crowdsale/validation/CappedCrowdsale.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; import "../token/ERC20/ERC20Mintable.sol"; +import "../token/ERC20/ERC20Detailed.sol"; /** * @title SampleCrowdsaleToken * @dev Very simple ERC20 Token that can be minted. * It is meant to be used in a crowdsale contract. */ -contract SampleCrowdsaleToken is ERC20Mintable { - - string public constant name = "Sample Crowdsale Token"; - string public constant symbol = "SCT"; - uint8 public constant decimals = 18; +contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { + constructor() public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {} } /** @@ -24,6 +22,8 @@ contract SampleCrowdsaleToken is ERC20Mintable { * In this example we are providing following extensions: * CappedCrowdsale - sets a max boundary for raised funds * RefundableCrowdsale - set a min goal to be reached and returns funds if it's not met + * MintedCrowdsale - assumes the token can be minted by the crowdsale, which does so + * when receiving purchases. * * After adding multiple features it's good practice to run integration tests * to ensure that subcontracts works together as intended. From bbe804a14bf901bc5f1742ec58665d4b5fd1a2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:43:44 -0300 Subject: [PATCH 079/205] Deleted unnecessary import. (#1437) * Deleted unnecessary import. * Added back SafeMath. * Removed another unnecessary import. --- contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol | 1 - contracts/token/ERC20/SafeERC20.sol | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index ca05f6d66..b8c9ede77 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -1,7 +1,6 @@ pragma solidity ^0.4.24; import "../validation/TimedCrowdsale.sol"; -import "../../token/ERC20/IERC20.sol"; import "../../math/SafeMath.sol"; /** diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 9e6bf6a20..2774afa08 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "./ERC20.sol"; import "./IERC20.sol"; +import "../../math/SafeMath.sol"; /** * @title SafeERC20 From 41e74dd8d8eea4749262bc9e5fa24c2f4a542742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 5 Oct 2018 22:18:59 -0300 Subject: [PATCH 080/205] Removed old, unused mocks. (#1382) (cherry picked from commit b17de011dc336ed329d70fb0c7950b67b8192292) --- contracts/mocks/ForceEther.sol | 16 ---------- contracts/mocks/MessageHelper.sol | 50 ------------------------------- 2 files changed, 66 deletions(-) delete mode 100644 contracts/mocks/ForceEther.sol delete mode 100644 contracts/mocks/MessageHelper.sol diff --git a/contracts/mocks/ForceEther.sol b/contracts/mocks/ForceEther.sol deleted file mode 100644 index 41cde563c..000000000 --- a/contracts/mocks/ForceEther.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.4.24; - - -// @title Force Ether into a contract. -// @notice even -// if the contract is not payable. -// @notice To use, construct the contract with the target as argument. -// @author Remco Bloemen -contract ForceEther { - - constructor() public payable { } - - function destroyAndSend(address recipient) public { - selfdestruct(recipient); - } -} diff --git a/contracts/mocks/MessageHelper.sol b/contracts/mocks/MessageHelper.sol deleted file mode 100644 index 63571714f..000000000 --- a/contracts/mocks/MessageHelper.sol +++ /dev/null @@ -1,50 +0,0 @@ -pragma solidity ^0.4.24; - - -contract MessageHelper { - - event Show(bytes32 b32, uint256 number, string text); - event Buy(bytes32 b32, uint256 number, string text, uint256 value); - - function showMessage( - bytes32 _message, - uint256 _number, - string _text - ) - public - returns (bool) - { - emit Show(_message, _number, _text); - return true; - } - - function buyMessage( - bytes32 _message, - uint256 _number, - string _text - ) - public - payable - returns (bool) - { - emit Buy( - _message, - _number, - _text, - msg.value); - return true; - } - - function fail() public { - require(false); - } - - function call(address _to, bytes _data) public returns (bool) { - // solium-disable-next-line security/no-low-level-calls - if (_to.call(_data)) - return true; - else - return false; - } - -} From 66bad4ff2a310fa1861abb25ba4ae192b1a0a7dd Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 8 Oct 2018 19:21:06 +0530 Subject: [PATCH 081/205] Removed selfdestruct from BreakInvariantBounty (#1385) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1384 * introduced claimable and cancelBounty * cancelBounty tests * Update BreakInvariantBounty.test.js (cherry picked from commit 41f84f8b402efcda35f84ea9d7ffca4bb5f86499) --- contracts/drafts/BreakInvariantBounty.sol | 26 +++++---- test/drafts/BreakInvariantBounty.test.js | 70 +++++++++++++++-------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/contracts/drafts/BreakInvariantBounty.sol b/contracts/drafts/BreakInvariantBounty.sol index 51ea06a06..940f8face 100644 --- a/contracts/drafts/BreakInvariantBounty.sol +++ b/contracts/drafts/BreakInvariantBounty.sol @@ -10,24 +10,25 @@ import "../ownership/Ownable.sol"; * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. */ contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimed; + bool private _claimable = true; mapping(address => address) private _researchers; event TargetCreated(address createdAddress); + event BountyCanceled(); /** * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. */ function() external payable { - require(!_claimed); + require(_claimable); } /** - * @dev Determine if the bounty was claimed. - * @return true if the bounty was claimed, false otherwise. + * @dev Determine if the bounty is claimable. + * @return false if the bounty was claimed, true otherwise. */ - function claimed() public view returns(bool) { - return _claimed; + function claimable() public view returns(bool) { + return _claimable; } /** @@ -47,20 +48,23 @@ contract BreakInvariantBounty is PullPayment, Ownable { * @param target contract */ function claim(Target target) public { - require(!_claimed); + require(_claimable); address researcher = _researchers[target]; require(researcher != address(0)); // Check Target contract invariants require(!target.checkInvariant()); _asyncTransfer(researcher, address(this).balance); - _claimed = true; + _claimable = false; } /** - * @dev Transfers the current balance to the owner and terminates the contract. + * @dev Cancels the bounty and transfers all funds to the owner */ - function destroy() public onlyOwner { - selfdestruct(owner()); + function cancelBounty() public onlyOwner{ + require(_claimable); + _asyncTransfer(owner(), address(this).balance); + _claimable = false; + emit BountyCanceled(); } /** diff --git a/test/drafts/BreakInvariantBounty.test.js b/test/drafts/BreakInvariantBounty.test.js index 037ff53ef..b9b97054d 100644 --- a/test/drafts/BreakInvariantBounty.test.js +++ b/test/drafts/BreakInvariantBounty.test.js @@ -1,6 +1,8 @@ -const { ethGetBalance, ethSendTransaction } = require('../helpers/web3'); -const expectEvent = require('../helpers/expectEvent'); -const { assertRevert } = require('../helpers/assertRevert'); +const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); +const { ether } = require('./helpers/ether'); +const { balanceDifference } = require('./helpers/balanceDiff'); +const expectEvent = require('./helpers/expectEvent'); +const { assertRevert } = require('./helpers/assertRevert'); const BreakInvariantBountyMock = artifacts.require('BreakInvariantBountyMock'); const TargetMock = artifacts.require('TargetMock'); @@ -9,7 +11,7 @@ require('chai') .use(require('chai-bignumber')(web3.BigNumber)) .should(); -const reward = new web3.BigNumber(web3.toWei(1, 'ether')); +const reward = ether(1); contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTarget]) { beforeEach(async function () { @@ -26,24 +28,9 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); }); - describe('destroy', function () { - it('returns all balance to the owner', async function () { - const ownerPreBalance = await ethGetBalance(owner); - await this.bounty.destroy({ from: owner, gasPrice: 0 }); - const ownerPostBalance = await ethGetBalance(owner); - - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); - ownerPostBalance.sub(ownerPreBalance).should.be.bignumber.equal(reward); - }); - - it('reverts when called by anyone', async function () { - await assertRevert(this.bounty.destroy({ from: anyone })); - }); - }); - describe('claim', function () { - it('is initially unclaimed', async function () { - (await this.bounty.claimed()).should.equal(false); + it('is initially claimable', async function () { + (await this.bounty.claimable()).should.equal(true); }); it('can create claimable target', async function () { @@ -85,8 +72,8 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar await this.bounty.claim(this.target.address, { from: researcher }); }); - it('is claimed', async function () { - (await this.bounty.claimed()).should.equal(true); + it('is not claimable', async function () { + (await this.bounty.claimable()).should.equal(false); }); it('no longer accepts rewards', async function () { @@ -106,5 +93,42 @@ contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTar }); }); }); + + describe('cancelBounty', function () { + context('before canceling', function () { + it('is claimable', async function () { + (await this.bounty.claimable()).should.equal(true); + }); + + it('can be canceled by the owner', async function () { + const { logs } = await this.bounty.cancelBounty({ from: owner }); + expectEvent.inLogs(logs, 'BountyCanceled'); + (await balanceDifference(owner, () => this.bounty.withdrawPayments(owner))) + .should.be.bignumber.equal(reward); + }); + + it('reverts when canceled by anyone', async function () { + await assertRevert(this.bounty.cancelBounty({ from: anyone })); + }); + }); + + context('after canceling', async function () { + beforeEach(async function () { + await this.bounty.cancelBounty({ from: owner }); + }); + + it('is not claimable', async function () { + (await this.bounty.claimable()).should.equal(false); + }); + + it('no longer accepts rewards', async function () { + await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); + }); + + it('reverts when recanceled', async function () { + await assertRevert(this.bounty.cancelBounty({ from: owner })); + }); + }); + }); }); }); From 8d6250cd5a66a79f0072f2c089510dda21f14830 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Mon, 8 Oct 2018 16:01:33 +0200 Subject: [PATCH 082/205] Add Arrays library with unit tests (#1209) (#1375) * Add Arrays library with unit tests (#1209) * prepared due to snapshot token requirements * add library with method to find upper bound * add unit test for basic and edge cases * Imporove documentation for Arrays library Simplify Arrays.test.js to use short arrays as test date * Added comment for uint256 mid variable. * Explaned why uint256 mid variable calculated as Math.average is safe to use as index of array. (cherry picked from commit f7e53d90fa638553ffc93e93fe1b12fc081bb774) --- contracts/mocks/ArraysImpl.sol | 18 +++++++ contracts/utils/Arrays.sol | 56 ++++++++++++++++++++++ test/utils/Arrays.test.js | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 contracts/mocks/ArraysImpl.sol create mode 100644 contracts/utils/Arrays.sol create mode 100644 test/utils/Arrays.test.js diff --git a/contracts/mocks/ArraysImpl.sol b/contracts/mocks/ArraysImpl.sol new file mode 100644 index 000000000..8a2b9ec51 --- /dev/null +++ b/contracts/mocks/ArraysImpl.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + +import "../utils/Arrays.sol"; + +contract ArraysImpl { + + using Arrays for uint256[]; + + uint256[] private array; + + constructor(uint256[] _array) public { + array = _array; + } + + function findUpperBound(uint256 _element) external view returns (uint256) { + return array.findUpperBound(_element); + } +} diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol new file mode 100644 index 000000000..6882ea995 --- /dev/null +++ b/contracts/utils/Arrays.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.23; + +import "../math/Math.sol"; + + +/** + * @title Arrays + * @dev Utility library of inline array functions + */ +library Arrays { + + /** + * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted + * array to find index of the element value. If element is found then returns it's index otherwise + * it returns index of first element which is grater than searched value. If searched element is + * bigger than any array element function then returns first index after last element (i.e. all + * values inside the array are smaller than the target). Complexity O(log n). + * @param array The array sorted in ascending order. + * @param element The element's value to be find. + * @return The calculated index value. Returns 0 for empty array. + */ + function findUpperBound( + uint256[] storage array, + uint256 element + ) + internal + view + returns (uint256) + { + if (array.length == 0) { + return 0; + } + + uint256 low = 0; + uint256 high = array.length; + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds down (it does integer division with truncation). + if (array[mid] > element) { + high = mid; + } else { + low = mid + 1; + } + } + + // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. + if (low > 0 && array[low - 1] == element) { + return low - 1; + } else { + return low; + } + } +} diff --git a/test/utils/Arrays.test.js b/test/utils/Arrays.test.js new file mode 100644 index 000000000..4bfc9eaba --- /dev/null +++ b/test/utils/Arrays.test.js @@ -0,0 +1,87 @@ +const ArraysImpl = artifacts.require('ArraysImpl'); + +const BigNumber = web3.BigNumber; + +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +contract('Arrays', function () { + context('Even number of elements', function () { + const EVEN_ELEMENTS_ARRAY = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(EVEN_ELEMENTS_ARRAY); + }); + + it('should return correct index for the basic case', async function () { + (await this.arrays.findUpperBound(16)).should.be.bignumber.equal(5); + }); + + it('should return 0 for the first element', async function () { + (await this.arrays.findUpperBound(11)).should.be.bignumber.equal(0); + }); + + it('should return index of the last element', async function () { + (await this.arrays.findUpperBound(20)).should.be.bignumber.equal(9); + }); + + it('should return first index after last element if searched value is over the upper boundary', async function () { + (await this.arrays.findUpperBound(32)).should.be.bignumber.equal(10); + }); + + it('should return 0 for the element under the lower boundary', async function () { + (await this.arrays.findUpperBound(2)).should.be.bignumber.equal(0); + }); + }); + + context('Odd number of elements', function () { + const ODD_ELEMENTS_ARRAY = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(ODD_ELEMENTS_ARRAY); + }); + + it('should return correct index for the basic case', async function () { + (await this.arrays.findUpperBound(16)).should.be.bignumber.equal(5); + }); + + it('should return 0 for the first element', async function () { + (await this.arrays.findUpperBound(11)).should.be.bignumber.equal(0); + }); + + it('should return index of the last element', async function () { + (await this.arrays.findUpperBound(21)).should.be.bignumber.equal(10); + }); + + it('should return first index after last element if searched value is over the upper boundary', async function () { + (await this.arrays.findUpperBound(32)).should.be.bignumber.equal(11); + }); + + it('should return 0 for the element under the lower boundary', async function () { + (await this.arrays.findUpperBound(2)).should.be.bignumber.equal(0); + }); + }); + + context('Array with gap', function () { + const WITH_GAP_ARRAY = [11, 12, 13, 14, 15, 20, 21, 22, 23, 24]; + + beforeEach(async function () { + this.arrays = await ArraysImpl.new(WITH_GAP_ARRAY); + }); + + it('should return index of first element in next filled range', async function () { + (await this.arrays.findUpperBound(17)).should.be.bignumber.equal(5); + }); + }); + + context('Empty array', function () { + beforeEach(async function () { + this.arrays = await ArraysImpl.new([]); + }); + + it('should always return 0 for empty array', async function () { + (await this.arrays.findUpperBound(10)).should.be.bignumber.equal(0); + }); + }); +}); From 9c76d28245868e2471b0c500ffc4e74c7a93647b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 8 Oct 2018 20:01:35 -0300 Subject: [PATCH 083/205] Added a constructor to BreakInvariantBounty. (#1395) (cherry picked from commit 3acc2b4216394d4d66b717f40891e64a99aed8c6) --- contracts/drafts/BreakInvariantBounty.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/drafts/BreakInvariantBounty.sol b/contracts/drafts/BreakInvariantBounty.sol index 940f8face..901ade023 100644 --- a/contracts/drafts/BreakInvariantBounty.sol +++ b/contracts/drafts/BreakInvariantBounty.sol @@ -10,12 +10,16 @@ import "../ownership/Ownable.sol"; * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. */ contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimable = true; + bool private _claimable; mapping(address => address) private _researchers; event TargetCreated(address createdAddress); event BountyCanceled(); + constructor() public { + _claimable = true; + } + /** * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. */ From a811a0be288ae5344ff51f2889022290e6e1dbce Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Tue, 9 Oct 2018 22:02:45 +0530 Subject: [PATCH 084/205] Improves Ownable events (#1397) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1392 * event tests added * constructor event added (cherry picked from commit af42c39e6cb835b220c2ce8ef6247f074707baf7) --- contracts/ownership/Ownable.sol | 5 ++--- test/ownership/Ownable.behavior.js | 8 ++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index e7d2810de..742321b50 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -9,8 +9,6 @@ pragma solidity ^0.4.24; contract Ownable { address private _owner; - - event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner @@ -23,6 +21,7 @@ contract Ownable { */ constructor() public { _owner = msg.sender; + emit OwnershipTransferred(address(0), _owner); } /** @@ -54,7 +53,7 @@ contract Ownable { * modifier anymore. */ function renounceOwnership() public onlyOwner { - emit OwnershipRenounced(_owner); + emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index eac3c10ce..baf609c57 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,5 +1,6 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); +const expectEvent = require('../helpers/expectEvent'); const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; @@ -14,7 +15,8 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { it('changes owner after transfer', async function () { (await this.ownable.isOwner({ from: anyone })).should.be.equal(false); - await this.ownable.transferOwnership(anyone, { from: owner }); + const { logs } = await this.ownable.transferOwnership(anyone, { from: owner }); + expectEvent.inLogs(logs, 'OwnershipTransferred'); (await this.ownable.owner()).should.equal(anyone); (await this.ownable.isOwner({ from: anyone })).should.be.equal(true); @@ -29,7 +31,9 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('loses owner after renouncement', async function () { - await this.ownable.renounceOwnership({ from: owner }); + const { logs } = await this.ownable.renounceOwnership({ from: owner }); + expectEvent.inLogs(logs, 'OwnershipTransferred'); + (await this.ownable.owner()).should.equal(ZERO_ADDRESS); }); From 9f5b73df37baad8654661f9341210912d52ebbcc Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 10 Oct 2018 00:16:09 +0530 Subject: [PATCH 085/205] added a test helper with common constants (#1400) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1206 (cherry picked from commit 58a42443dfe57a2c0e161539d0b363e5ca7bf8d9) --- test/access/Roles.test.js | 4 +--- test/access/roles/PublicRole.behavior.js | 2 +- test/crowdsale/AllowanceCrowdsale.test.js | 2 +- test/crowdsale/Crowdsale.test.js | 2 +- test/drafts/ERC20Migrator.test.js | 4 +--- test/examples/SimpleToken.test.js | 3 +-- test/helpers/constants.js | 6 ++++++ test/math/SafeMath.test.js | 7 +++---- test/ownership/Ownable.behavior.js | 3 +-- test/ownership/Secondary.test.js | 4 +--- test/payment/ConditionalEscrow.test.js | 3 ++- test/payment/Escrow.behavior.js | 3 ++- test/payment/PullPayment.test.js | 3 ++- test/payment/RefundEscrow.test.js | 5 +++-- test/payment/SplitPayment.test.js | 5 +++-- test/token/ERC20/ERC20.test.js | 3 +-- test/token/ERC20/TokenVesting.test.js | 2 +- test/token/ERC20/behaviors/ERC20Burnable.behavior.js | 2 +- test/token/ERC20/behaviors/ERC20Mintable.behavior.js | 3 +-- test/token/ERC721/ERC721.behavior.js | 2 +- test/token/ERC721/ERC721MintBurn.behavior.js | 2 +- test/token/ERC721/ERC721PausedToken.behavior.js | 2 +- 22 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 test/helpers/constants.js diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 7d5573cec..76517492c 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -1,13 +1,11 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const RolesMock = artifacts.require('RolesMock'); require('chai') .should(); contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.roles = await RolesMock.new(); }); diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index f1c723b78..a3067f88e 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -1,4 +1,5 @@ const { assertRevert } = require('../../helpers/assertRevert'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const expectEvent = require('../../helpers/expectEvent'); require('chai') @@ -10,7 +11,6 @@ function capitalize (str) { function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename) { rolename = capitalize(rolename); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; describe('should behave like public role', function () { beforeEach('check preconditions', async function () { diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index ee6a063f2..82a5b6410 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,6 +1,7 @@ const { ether } = require('../helpers/ether'); const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -16,7 +17,6 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW const value = ether(0.42); const expectedTokenAmount = rate.mul(value); const tokenAllowance = new BigNumber('1e22'); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { this.token = await SimpleToken.new({ from: tokenWallet }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 556855796..89fd53b2d 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,6 +1,7 @@ const { assertRevert } = require('../helpers/assertRevert'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -16,7 +17,6 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { const value = ether(42); const tokenSupply = new BigNumber('1e22'); const expectedTokenAmount = rate.mul(value); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; it('requires a non-null token', async function () { await assertRevert( diff --git a/test/drafts/ERC20Migrator.test.js b/test/drafts/ERC20Migrator.test.js index 315a7ea78..608dce860 100644 --- a/test/drafts/ERC20Migrator.test.js +++ b/test/drafts/ERC20Migrator.test.js @@ -1,5 +1,5 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const ERC20Mock = artifacts.require('ERC20Mock'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20Migrator = artifacts.require('ERC20Migrator'); @@ -11,8 +11,6 @@ require('chai') .should(); contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - const totalSupply = 200; it('reverts with a null legacy token address', async function () { diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index a28cf4641..49b8a7aa4 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -1,4 +1,5 @@ const { decodeLogs } = require('../helpers/decodeLogs'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const SimpleToken = artifacts.require('SimpleToken'); const BigNumber = web3.BigNumber; @@ -10,8 +11,6 @@ require('chai') contract('SimpleToken', function ([_, creator]) { let token; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { token = await SimpleToken.new({ from: creator }); }); diff --git a/test/helpers/constants.js b/test/helpers/constants.js new file mode 100644 index 000000000..70d2242a3 --- /dev/null +++ b/test/helpers/constants.js @@ -0,0 +1,6 @@ +const BigNumber = web3.BigNumber; + +module.exports = { + ZERO_ADDRESS: '0x0000000000000000000000000000000000000000', + MAX_UINT256: new BigNumber(2).pow(256).minus(1), +}; diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index 0174bd0ac..56cedeb84 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,4 +1,5 @@ const { assertRevert } = require('../helpers/assertRevert'); +const { MAX_UINT256 } = require('../helpers/constants'); const BigNumber = web3.BigNumber; const SafeMathMock = artifacts.require('SafeMathMock'); @@ -8,8 +9,6 @@ require('chai') .should(); contract('SafeMath', function () { - const MAX_UINT = new BigNumber(2).pow(256).minus(1); - beforeEach(async function () { this.safeMath = await SafeMathMock.new(); }); @@ -23,7 +22,7 @@ contract('SafeMath', function () { }); it('throws a revert error on addition overflow', async function () { - const a = MAX_UINT; + const a = MAX_UINT256; const b = new BigNumber(1); await assertRevert(this.safeMath.add(a, b)); @@ -62,7 +61,7 @@ contract('SafeMath', function () { }); it('throws a revert error on multiplication overflow', async function () { - const a = MAX_UINT; + const a = MAX_UINT256; const b = new BigNumber(2); await assertRevert(this.safeMath.mul(a, b)); diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index baf609c57..1e2fd7564 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,8 +1,7 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const expectEvent = require('../helpers/expectEvent'); - -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; +const { ZERO_ADDRESS } = require('../helpers/constants'); require('chai') .should(); diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 000d0af11..31676be79 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,13 +1,11 @@ const { assertRevert } = require('../helpers/assertRevert'); - +const { ZERO_ADDRESS } = require('../helpers/constants'); const SecondaryMock = artifacts.require('SecondaryMock'); require('chai') .should(); contract('Secondary', function ([_, primary, newPrimary, anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.secondary = await SecondaryMock.new({ from: primary }); }); diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/ConditionalEscrow.test.js index 5115fee48..03eed68f7 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/ConditionalEscrow.test.js @@ -1,6 +1,7 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -24,7 +25,7 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) { }); context('when withdrawal is disallowed', function () { - const amount = web3.toWei(23.0, 'ether'); + const amount = ether(23.0); beforeEach(async function () { await this.escrow.setAllowed(payee, false); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 761aecd89..28abd5af8 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -2,6 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -10,7 +11,7 @@ require('chai') .should(); function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { - const amount = web3.toWei(42.0, 'ether'); + const amount = ether(42.0); describe('as an escrow', function () { describe('deposits', function () { diff --git a/test/payment/PullPayment.test.js b/test/payment/PullPayment.test.js index 1eab3911f..1f4bcc525 100644 --- a/test/payment/PullPayment.test.js +++ b/test/payment/PullPayment.test.js @@ -1,4 +1,5 @@ const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -9,7 +10,7 @@ require('chai') const PullPaymentMock = artifacts.require('PullPaymentMock'); contract('PullPayment', function ([_, payer, payee1, payee2]) { - const amount = web3.toWei(17.0, 'ether'); + const amount = ether(17.0); beforeEach(async function () { this.contract = await PullPaymentMock.new({ value: amount }); diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index e412816c4..1bd1a41c2 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -2,6 +2,8 @@ const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -12,9 +14,8 @@ require('chai') const RefundEscrow = artifacts.require('RefundEscrow'); contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee2]) { - const amount = web3.toWei(54.0, 'ether'); + const amount = ether(54.0); const refundees = [refundee1, refundee2]; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; it('requires a non-null beneficiary', async function () { await expectThrow( diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index 05cc0b701..c1ed22ead 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -1,4 +1,6 @@ const { ethGetBalance, ethSendTransaction } = require('../helpers/web3'); +const { ether } = require('../helpers/ether'); +const { ZERO_ADDRESS } = require('./../helpers/constants'); const BigNumber = web3.BigNumber; @@ -11,8 +13,7 @@ const { EVMRevert } = require('../helpers/EVMRevert.js'); const SplitPayment = artifacts.require('SplitPayment'); contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { - const amount = web3.toWei(1.0, 'ether'); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + const amount = ether(1.0); it('rejects an empty set of payees', async function () { await expectThrow(SplitPayment.new([], []), EVMRevert); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index f9568b87e..7f4981d21 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const ERC20 = artifacts.require('ERC20Mock'); @@ -10,8 +11,6 @@ require('chai') .should(); contract('ERC20', function ([_, owner, recipient, anotherAccount]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - beforeEach(async function () { this.token = await ERC20.new(owner, 100); }); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index 1fe9326f5..b88f8a673 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -3,6 +3,7 @@ const { EVMRevert } = require('../../helpers/EVMRevert'); const { latestTime } = require('../../helpers/latestTime'); const { increaseTimeTo, duration } = require('../../helpers/increaseTime'); const { ethGetBlock } = require('../../helpers/web3'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -15,7 +16,6 @@ const TokenVesting = artifacts.require('TokenVesting'); contract('TokenVesting', function ([_, owner, beneficiary]) { const amount = new BigNumber(1000); - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; beforeEach(async function () { this.start = (await latestTime()) + duration.minutes(1); // +1 minute so it starts after contract instantiation diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index cf0190046..996beb0e3 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -1,8 +1,8 @@ const { assertRevert } = require('../../../helpers/assertRevert'); const expectEvent = require('../../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../../helpers/constants'); const BigNumber = web3.BigNumber; -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; require('chai') .use(require('chai-bignumber')(BigNumber)) diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index 16126d99a..a5812f655 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../../helpers/assertRevert'); const expectEvent = require('../../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -8,8 +9,6 @@ require('chai') .should(); function shouldBehaveLikeERC20Mintable (minter, [anyone]) { - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - describe('as a mintable token', function () { describe('mint', function () { const amount = 100; diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index 03e83fabe..8da645d33 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,5 +1,6 @@ const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const { assertRevert } = require('../../helpers/assertRevert'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); const _ = require('lodash'); @@ -19,7 +20,6 @@ function shouldBehaveLikeERC721 ( const firstTokenId = 1; const secondTokenId = 2; const unknownTokenId = 3; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const RECEIVER_MAGIC_VALUE = '0x150b7a02'; describe('like an ERC721', function () { diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index ab54a6ae6..e40356561 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; require('chai') @@ -15,7 +16,6 @@ function shouldBehaveLikeMintAndBurnERC721 ( const secondTokenId = 2; const thirdTokenId = 3; const unknownTokenId = 4; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const MOCK_URI = 'https://example.com'; describe('like a mintable and burnable ERC721', function () { diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index d14e6a395..a7196d837 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -1,5 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { sendTransaction } = require('../../helpers/sendTransaction'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -11,7 +12,6 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { const firstTokenId = 1; const mintedTokens = 1; const mockData = '0x42'; - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; describe('like a paused ERC721', function () { beforeEach(async function () { From 8204f6a71fcb1597e3c92117290600f4e752ca19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 19:07:34 -0300 Subject: [PATCH 086/205] Improved some ERC721 internal shenanigans (#1450) * Made _clearApproval private, added clarifying comments in _addTokenTo and _removeTokenFrom. * Added approval information. --- contracts/token/ERC721/ERC721.sol | 31 ++++++++++++--------- contracts/token/ERC721/ERC721Enumerable.sol | 5 ++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 3dc243874..ec0763b96 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -262,21 +262,10 @@ contract ERC721 is ERC165, IERC721 { emit Transfer(owner, address(0), tokenId); } - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param owner owner of the token - * @param tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(address owner, uint256 tokenId) internal { - require(ownerOf(tokenId) == owner); - if (_tokenApprovals[tokenId] != address(0)) { - _tokenApprovals[tokenId] = address(0); - } - } - /** * @dev Internal function to add a token ID to the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ @@ -288,6 +277,9 @@ contract ERC721 is ERC165, IERC721 { /** * @dev Internal function to remove a token ID from the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ @@ -322,4 +314,17 @@ contract ERC721 is ERC165, IERC721 { msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } + + /** + * @dev Private function to clear current approval of a given token ID + * Reverts if the given address is not indeed the owner of the token + * @param owner owner of the token + * @param tokenId uint256 ID of the token to be transferred + */ + function _clearApproval(address owner, uint256 tokenId) private { + require(ownerOf(tokenId) == owner); + if (_tokenApprovals[tokenId] != address(0)) { + _tokenApprovals[tokenId] = address(0); + } + } } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index 0a2797eed..c85514720 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -72,6 +72,8 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { /** * @dev Internal function to add a token ID to the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ @@ -84,6 +86,9 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { /** * @dev Internal function to remove a token ID from the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ From 1ac1ac984ec3f5ab10d01150480670f30ecb4fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 15:12:16 -0300 Subject: [PATCH 087/205] Fixed how allowance crowdsale checks remaining tokens. (#1449) --- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 6 +++++- test/crowdsale/AllowanceCrowdsale.test.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index ec9918feb..346275c7d 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -4,6 +4,7 @@ import "../Crowdsale.sol"; import "../../token/ERC20/IERC20.sol"; import "../../token/ERC20/SafeERC20.sol"; import "../../math/SafeMath.sol"; +import "../../math/Math.sol"; /** * @title AllowanceCrowdsale @@ -36,7 +37,10 @@ contract AllowanceCrowdsale is Crowdsale { * @return Amount of tokens left in the allowance */ function remainingTokens() public view returns (uint256) { - return token().allowance(_tokenWallet, this); + return Math.min( + token().balanceOf(_tokenWallet), + token().allowance(_tokenWallet, this) + ); } /** diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 4298dcce6..413d25544 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -69,6 +69,17 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); (await this.crowdsale.remainingTokens()).should.be.bignumber.equal(remainingAllowance); }); + + context('when the allowance is larger than the token amount', function () { + beforeEach(async function () { + const amount = await this.token.balanceOf(tokenWallet); + await this.token.approve(this.crowdsale.address, amount.plus(1), { from: tokenWallet }); + }); + + it('should report the amount instead of the allowance', async function () { + (await this.crowdsale.remainingTokens()).should.be.bignumber.equal(await this.token.balanceOf(tokenWallet)); + }); + }); }); describe('when token wallet is different from token address', function () { From a936cbf5fbe78fb160a2fa679cdf434cbed95426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 15:37:24 -0300 Subject: [PATCH 088/205] InitialRate must be strictly larger than finalRate. (#1441) --- .../crowdsale/price/IncreasingPriceCrowdsale.sol | 10 +++++++++- test/crowdsale/IncreasingPriceCrowdsale.test.js | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 4d2b44931..c86353c0f 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -22,11 +22,19 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { */ constructor(uint256 initialRate, uint256 finalRate) internal { require(finalRate > 0); - require(initialRate >= finalRate); + require(initialRate > finalRate); _initialRate = initialRate; _finalRate = finalRate; } + /** + * The base rate function is overridden to revert, since this crowdsale doens't use it, and + * all calls to it are a mistake. + */ + function rate() public view returns(uint256) { + revert(); + } + /** * @return the initial rate of the crowdsale. */ diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 51946b5ee..41906d224 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -34,13 +34,19 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) this.token = await SimpleToken.new(); }); - it('rejects a final rate larger than the initial rate', async function () { + it('reverts with a final rate larger than the initial rate', async function () { await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); - it('rejects a final rate of zero', async function () { + it('reverts with a final equal to the initial rate', async function () { + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( + this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate + )); + }); + + it('reverts with a final rate of zero', async function () { await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); @@ -59,6 +65,10 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) (await this.crowdsale.finalRate()).should.be.bignumber.equal(finalRate); }); + it('reverts when the base Crowdsale\'s rate function is called', async function () { + await shouldFail.reverting(this.crowdsale.rate()); + }); + it('returns a rate of 0 before the crowdsale starts', async function () { (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); }); From 6d415c508be94ef8391ed6525df365452466da76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 17:42:20 -0300 Subject: [PATCH 089/205] Crowdsale.buyTokens is now nonReentrant. (#1438) --- contracts/crowdsale/Crowdsale.sol | 7 +++++-- contracts/utils/ReentrancyGuard.sol | 9 ++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index 9aa550519..a0c227607 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../math/SafeMath.sol"; import "../token/ERC20/SafeERC20.sol"; +import "../utils/ReentrancyGuard.sol"; /** * @title Crowdsale @@ -16,7 +17,7 @@ import "../token/ERC20/SafeERC20.sol"; * the methods to add functionality. Consider using 'super' where appropriate to concatenate * behavior. */ -contract Crowdsale { +contract Crowdsale is ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for IERC20; @@ -111,9 +112,11 @@ contract Crowdsale { /** * @dev low level token purchase ***DO NOT OVERRIDE*** + * This function has a non-reentrancy guard, so it shouldn't be called by + * another `nonReentrant` function. * @param beneficiary Recipient of the token purchase */ - function buyTokens(address beneficiary) public payable { + function buyTokens(address beneficiary) public nonReentrant payable { uint256 weiAmount = msg.value; _preValidatePurchase(beneficiary, weiAmount); diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 368f2720f..7a2895da2 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -19,11 +19,10 @@ contract ReentrancyGuard { /** * @dev Prevents a contract from calling itself, directly or indirectly. - * If you mark a function `nonReentrant`, you should also - * mark it `external`. Calling one `nonReentrant` function from - * another is not supported. Instead, you can implement a - * `private` function doing the actual work, and an `external` - * wrapper marked as `nonReentrant`. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and make it call a + * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; From 80458ebc72f1c7c9695416edbe26690f72e406a0 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 19 Oct 2018 17:35:04 -0600 Subject: [PATCH 090/205] Add warning about trading tokens before refundable crowdsale goal is met (#1452) This attack was reported in https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 --- .../crowdsale/distribution/RefundableCrowdsale.sol | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index d670f9ced..9b814cd7d 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -8,6 +8,19 @@ import "../../payment/escrow/RefundEscrow.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. + * WARNING: note that if you allow tokens to be traded before the goal + * is met, then an attack is possible in which the attacker purchases + * tokens from the crowdsale and when they sees that the goal is + * unlikely to be met, they sell their tokens (possibly at a discount). + * The attacker will be refunded when the crowdsale is finalized, and + * the users that purchased from them will be left with worthless + * tokens. There are many possible ways to avoid this, like making the + * the crowdsale inherit from PostDeliveryCrowdsale, or imposing + * restrictions on token trading until the crowdsale is finalized. + * This is being discussed in + * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 + * This contract will be updated when we agree on a general solution + * for this problem. */ contract RefundableCrowdsale is FinalizableCrowdsale { using SafeMath for uint256; From 2e14386eda4681ae63b66fc27d25b587c4f0bde3 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 15:41:43 -0300 Subject: [PATCH 091/205] fix readme snippet so it is concrete (cherry picked from commit 651f6d8b57f5b67cda69656c70b8db4136f7d72f) --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a912ac734..17bfac0b1 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,14 @@ npm install openzeppelin-solidity To write your custom contracts, import ours and extend them through inheritance. ```solidity -import 'openzeppelin-solidity/contracts/token/ERC721/ERC721.sol'; +pragma solidity ^0.4.24; + +import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol'; import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol'; -contract MyNFT is ERC721, ERC721Mintable { +contract MyNFT is ERC721Full, ERC721Mintable { + constructors() ERC721Full("MyNFT", "MNFT") public { + } } ``` From 2a8146a45dbcb01ad269bf568f2cef7b73c448a1 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 7 Sep 2018 15:45:29 -0300 Subject: [PATCH 092/205] Fix README snippet typo (cherry picked from commit 0b8296e52596db8ef97f313fe3507cac8fbbcde3) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 17bfac0b1..f196bf5aa 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol'; import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol'; contract MyNFT is ERC721Full, ERC721Mintable { - constructors() ERC721Full("MyNFT", "MNFT") public { + constructor() ERC721Full("MyNFT", "MNFT") public { } } ``` From 7ea34d9e977bfe4fe75d4db61d716d5830bab890 Mon Sep 17 00:00:00 2001 From: Jerome de Tychey Date: Mon, 10 Sep 2018 17:06:52 +0200 Subject: [PATCH 093/205] Update ERC20.sol (#1313) correct typo in doc (cherry picked from commit b644c72eb083d7a84a5c9924ec8012a7c29290fd) --- contracts/token/ERC20/ERC20.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 22b7df3c5..09049c59a 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -29,7 +29,7 @@ contract ERC20 is IERC20 { /** * @dev Gets the balance of the specified address. - * @param owner The address to query the the balance of. + * @param owner The address to query the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { From f8b0cec15bef6f420da90b7b8732bc0897015dd5 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Wed, 12 Sep 2018 17:49:00 +0200 Subject: [PATCH 094/205] Add unit test specific to Address utils (#1251) (#1316) (cherry picked from commit 7825caa1fdf8bec80ad43f4da15cf5ee4c9a8e3f) --- contracts/mocks/AddressImpl.sol | 15 +++++++++++++++ test/Address.test.js | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 contracts/mocks/AddressImpl.sol create mode 100644 test/Address.test.js diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol new file mode 100644 index 000000000..b46fd06c3 --- /dev/null +++ b/contracts/mocks/AddressImpl.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.24; + +import "../utils/Address.sol"; + + +contract AddressImpl { + function isContract(address account) + external + view + returns (bool) + { + return Address.isContract(account); + } + +} diff --git a/test/Address.test.js b/test/Address.test.js new file mode 100644 index 000000000..f41e57565 --- /dev/null +++ b/test/Address.test.js @@ -0,0 +1,20 @@ +const AddressImpl = artifacts.require('AddressImpl'); +const SimpleToken = artifacts.require('SimpleToken'); + +require('chai') + .should(); + +contract('Address', function ([_, anyone]) { + beforeEach(async function () { + this.mock = await AddressImpl.new(); + }); + + it('should return false for account address', async function () { + (await this.mock.isContract(anyone)).should.equal(false); + }); + + it('should return true for contract address', async function () { + const contract = await SimpleToken.new(); + (await this.mock.isContract(contract.address)).should.equal(true); + }); +}); From a3bb56769e3296c612384a744f42ebef1b1ba395 Mon Sep 17 00:00:00 2001 From: Roman Exempliarov Date: Mon, 17 Sep 2018 23:21:01 +0300 Subject: [PATCH 095/205] Remove lodash from tests (#1323) (cherry picked from commit d062352de78b02435e793ed13991dfdf210f8a29) --- test/helpers/sendTransaction.js | 3 +-- test/token/ERC721/ERC721.behavior.js | 5 +++-- test/token/ERC721/ERC721Full.test.js | 16 ++++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/test/helpers/sendTransaction.js b/test/helpers/sendTransaction.js index 741063209..e49376b44 100644 --- a/test/helpers/sendTransaction.js +++ b/test/helpers/sendTransaction.js @@ -1,9 +1,8 @@ -const _ = require('lodash'); const ethjsABI = require('ethjs-abi'); function findMethod (abi, name, args) { for (let i = 0; i < abi.length; i++) { - const methodArgs = _.map(abi[i].inputs, 'type').join(','); + const methodArgs = abi[i].inputs.map(input => input.type).join(','); if ((abi[i].name === name) && (methodArgs === args)) { return abi[i]; } diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index 8da645d33..22c24cd8a 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -3,7 +3,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); -const _ = require('lodash'); const ERC721Receiver = artifacts.require('ERC721ReceiverMock.sol'); const BigNumber = web3.BigNumber; @@ -175,7 +174,9 @@ function shouldBehaveLikeERC721 ( it('keeps same tokens by index', async function () { if (!this.token.tokenOfOwnerByIndex) return; - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(owner, i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenOfOwnerByIndex(owner, i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); }); diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index ef3f67bc8..30e4547c8 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -1,7 +1,6 @@ const { assertRevert } = require('../../helpers/assertRevert'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); -const _ = require('lodash'); const BigNumber = web3.BigNumber; const ERC721FullMock = artifacts.require('ERC721FullMock.sol'); @@ -172,7 +171,9 @@ contract('ERC721Full', function ([ it('returns correct token IDs for target', async function () { (await this.token.balanceOf(another)).toNumber().should.be.equal(2); - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(another, i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenOfOwnerByIndex(another, i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); @@ -185,7 +186,9 @@ contract('ERC721Full', function ([ describe('tokenByIndex', function () { it('should return all tokens', async function () { - const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenByIndex(i))); + const tokensListed = await Promise.all( + [0, 1].map(i => this.token.tokenByIndex(i)) + ); tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]); }); @@ -204,9 +207,10 @@ contract('ERC721Full', function ([ (await this.token.totalSupply()).toNumber().should.be.equal(3); - const tokensListed = await Promise.all(_.range(3).map(i => this.token.tokenByIndex(i))); - const expectedTokens = _.filter( - [firstTokenId, secondTokenId, newTokenId, anotherNewTokenId], + const tokensListed = await Promise.all( + [0, 1, 2].map(i => this.token.tokenByIndex(i)) + ); + const expectedTokens = [firstTokenId, secondTokenId, newTokenId, anotherNewTokenId].filter( x => (x !== tokenId) ); tokensListed.map(t => t.toNumber()).should.have.members(expectedTokens); From 49d2dd9e085f4141fcbaa5fee30dd6960ca5d158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn?= Date: Tue, 18 Sep 2018 16:24:51 -0300 Subject: [PATCH 096/205] Add Mock suffix to variable names #1172 (#1324) * Add Mock suffix to variable names #1172 * Add Impl suffix to variable names (cherry picked from commit 4b21fcf5af6b411d6c39b0616e25d91c811d0768) --- test/crowdsale/AllowanceCrowdsale.test.js | 6 +++--- test/crowdsale/CappedCrowdsale.test.js | 6 +++--- test/crowdsale/FinalizableCrowdsale.test.js | 4 ++-- test/crowdsale/IncreasingPriceCrowdsale.test.js | 8 ++++---- test/crowdsale/MintedCrowdsale.test.js | 6 +++--- test/crowdsale/PostDeliveryCrowdsale.test.js | 4 ++-- test/crowdsale/RefundableCrowdsale.test.js | 6 +++--- test/crowdsale/TimedCrowdsale.test.js | 10 ++++++---- test/drafts/Counter.test.js | 4 ++-- test/drafts/ERC1046/TokenMetadata.test.js | 4 ++-- test/introspection/ERC165.test.js | 4 ++-- test/token/ERC20/ERC20.test.js | 4 ++-- test/token/ERC20/ERC20Pausable.test.js | 4 ++-- test/token/ERC721/ERC721.behavior.js | 12 ++++++------ test/token/ERC721/ERC721.test.js | 4 ++-- test/token/ERC721/ERC721Burnable.test.js | 4 ++-- test/token/ERC721/ERC721Mintable.test.js | 4 ++-- test/token/ERC721/ERC721Pausable.test.js | 4 ++-- 18 files changed, 50 insertions(+), 48 deletions(-) diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 82a5b6410..f9a7969b9 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -9,7 +9,7 @@ const should = require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const AllowanceCrowdsale = artifacts.require('AllowanceCrowdsaleImpl'); +const AllowanceCrowdsaleImpl = artifacts.require('AllowanceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenWallet]) { @@ -20,7 +20,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW beforeEach(async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - this.crowdsale = await AllowanceCrowdsale.new(rate, wallet, this.token.address, tokenWallet); + this.crowdsale = await AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, tokenWallet); await this.token.approve(this.crowdsale.address, tokenAllowance, { from: tokenWallet }); }); @@ -73,7 +73,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('when token wallet is different from token address', function () { it('creation reverts', async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - await assertRevert(AllowanceCrowdsale.new(rate, wallet, this.token.address, ZERO_ADDRESS)); + await assertRevert(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); }); }); }); diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index 94ed0aedd..5ccfafba3 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -8,7 +8,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const CappedCrowdsale = artifacts.require('CappedCrowdsaleImpl'); +const CappedCrowdsaleImpl = artifacts.require('CappedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('CappedCrowdsale', function ([_, wallet]) { @@ -23,14 +23,14 @@ contract('CappedCrowdsale', function ([_, wallet]) { it('rejects a cap of zero', async function () { await expectThrow( - CappedCrowdsale.new(rate, wallet, this.token.address, 0), + CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0), EVMRevert, ); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await CappedCrowdsale.new(rate, wallet, this.token.address, cap); + this.crowdsale = await CappedCrowdsaleImpl.new(rate, wallet, this.token.address, cap); await this.token.transfer(this.crowdsale.address, tokenSupply); }); diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index df7a743dd..187c67a36 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -10,7 +10,7 @@ const should = require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const FinalizableCrowdsale = artifacts.require('FinalizableCrowdsaleImpl'); +const FinalizableCrowdsaleImpl = artifacts.require('FinalizableCrowdsaleImpl'); const ERC20 = artifacts.require('ERC20'); contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { @@ -27,7 +27,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { this.afterClosingTime = this.closingTime + duration.seconds(1); this.token = await ERC20.new(); - this.crowdsale = await FinalizableCrowdsale.new( + this.crowdsale = await FinalizableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address ); }); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index c62c17d89..767b5f8e5 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -10,7 +10,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const IncreasingPriceCrowdsale = artifacts.require('IncreasingPriceCrowdsaleImpl'); +const IncreasingPriceCrowdsaleImpl = artifacts.require('IncreasingPriceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -36,20 +36,20 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('rejects a final rate larger than the initial rate', async function () { - await assertRevert(IncreasingPriceCrowdsale.new( + await assertRevert(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); it('rejects a final rate of zero', async function () { - await assertRevert(IncreasingPriceCrowdsale.new( + await assertRevert(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await IncreasingPriceCrowdsale.new( + this.crowdsale = await IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, finalRate ); await this.token.transfer(this.crowdsale.address, tokenSupply); diff --git a/test/crowdsale/MintedCrowdsale.test.js b/test/crowdsale/MintedCrowdsale.test.js index e254ddf1b..a3c846b2d 100644 --- a/test/crowdsale/MintedCrowdsale.test.js +++ b/test/crowdsale/MintedCrowdsale.test.js @@ -4,7 +4,7 @@ const { assertRevert } = require('../helpers/assertRevert'); const BigNumber = web3.BigNumber; -const MintedCrowdsale = artifacts.require('MintedCrowdsaleImpl'); +const MintedCrowdsaleImpl = artifacts.require('MintedCrowdsaleImpl'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20 = artifacts.require('ERC20'); @@ -15,7 +15,7 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] describe('using ERC20Mintable', function () { beforeEach(async function () { this.token = await ERC20Mintable.new({ from: deployer }); - this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address); + this.crowdsale = await MintedCrowdsaleImpl.new(rate, wallet, this.token.address); await this.token.addMinter(this.crowdsale.address, { from: deployer }); await this.token.renounceMinter({ from: deployer }); @@ -31,7 +31,7 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] describe('using non-mintable token', function () { beforeEach(async function () { this.token = await ERC20.new(); - this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address); + this.crowdsale = await MintedCrowdsaleImpl.new(rate, wallet, this.token.address); }); it('rejects bare payments', async function () { diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index e95c5a1f4..94ebd808b 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -11,7 +11,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const PostDeliveryCrowdsale = artifacts.require('PostDeliveryCrowdsaleImpl'); +const PostDeliveryCrowdsaleImpl = artifacts.require('PostDeliveryCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -28,7 +28,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { this.closingTime = this.openingTime + duration.weeks(1); this.afterClosingTime = this.closingTime + duration.seconds(1); this.token = await SimpleToken.new(); - this.crowdsale = await PostDeliveryCrowdsale.new( + this.crowdsale = await PostDeliveryCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address ); await this.token.transfer(this.crowdsale.address, tokenSupply); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 3a5305ceb..749ec5cac 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -12,7 +12,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const RefundableCrowdsale = artifacts.require('RefundableCrowdsaleImpl'); +const RefundableCrowdsaleImpl = artifacts.require('RefundableCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyone]) { @@ -37,7 +37,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon it('rejects a goal of zero', async function () { await expectThrow( - RefundableCrowdsale.new( + RefundableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address, 0, ), EVMRevert, @@ -46,7 +46,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await RefundableCrowdsale.new( + this.crowdsale = await RefundableCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address, goal ); diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index 4c7eff303..df3e01c81 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -11,7 +11,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const TimedCrowdsale = artifacts.require('TimedCrowdsaleImpl'); +const TimedCrowdsaleImpl = artifacts.require('TimedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { @@ -32,20 +32,22 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('rejects an opening time in the past', async function () { - await expectThrow(TimedCrowdsale.new( + await expectThrow(TimedCrowdsaleImpl.new( (await latestTime()) - duration.days(1), this.closingTime, rate, wallet, this.token.address ), EVMRevert); }); it('rejects a closing time before the opening time', async function () { - await expectThrow(TimedCrowdsale.new( + await expectThrow(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - duration.seconds(1), rate, wallet, this.token.address ), EVMRevert); }); context('with crowdsale', function () { beforeEach(async function () { - this.crowdsale = await TimedCrowdsale.new(this.openingTime, this.closingTime, rate, wallet, this.token.address); + this.crowdsale = await TimedCrowdsaleImpl.new( + this.openingTime, this.closingTime, rate, wallet, this.token.address + ); await this.token.transfer(this.crowdsale.address, tokenSupply); }); diff --git a/test/drafts/Counter.test.js b/test/drafts/Counter.test.js index ca661c113..8a2929d93 100644 --- a/test/drafts/Counter.test.js +++ b/test/drafts/Counter.test.js @@ -1,5 +1,5 @@ -const Counter = artifacts.require('CounterImpl'); +const CounterImpl = artifacts.require('CounterImpl'); require('chai') .use(require('chai-bignumber')(web3.BigNumber)) @@ -11,7 +11,7 @@ const KEY2 = web3.sha3('key2'); contract('Counter', function ([_, owner]) { beforeEach(async function () { - this.mock = await Counter.new({ from: owner }); + this.mock = await CounterImpl.new({ from: owner }); }); context('custom key', async function () { diff --git a/test/drafts/ERC1046/TokenMetadata.test.js b/test/drafts/ERC1046/TokenMetadata.test.js index ef0a2ca3d..9810d9119 100644 --- a/test/drafts/ERC1046/TokenMetadata.test.js +++ b/test/drafts/ERC1046/TokenMetadata.test.js @@ -1,4 +1,4 @@ -const ERC20WithMetadata = artifacts.require('ERC20WithMetadataMock'); +const ERC20WithMetadataMock = artifacts.require('ERC20WithMetadataMock'); require('chai') .should(); @@ -7,7 +7,7 @@ const metadataURI = 'https://example.com'; describe('ERC20WithMetadata', function () { beforeEach(async function () { - this.token = await ERC20WithMetadata.new(metadataURI); + this.token = await ERC20WithMetadataMock.new(metadataURI); }); it('responds with the metadata', async function () { diff --git a/test/introspection/ERC165.test.js b/test/introspection/ERC165.test.js index 37a24637d..dc04edaa2 100644 --- a/test/introspection/ERC165.test.js +++ b/test/introspection/ERC165.test.js @@ -1,14 +1,14 @@ const { shouldSupportInterfaces } = require('./SupportsInterface.behavior'); const { assertRevert } = require('../helpers/assertRevert'); -const ERC165 = artifacts.require('ERC165Mock'); +const ERC165Mock = artifacts.require('ERC165Mock'); require('chai') .should(); contract('ERC165', function () { beforeEach(async function () { - this.mock = await ERC165.new(); + this.mock = await ERC165Mock.new(); }); it('does not allow 0xffffffff', async function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 7f4981d21..5399ae584 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -2,7 +2,7 @@ const { assertRevert } = require('../../helpers/assertRevert'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const ERC20 = artifacts.require('ERC20Mock'); +const ERC20Mock = artifacts.require('ERC20Mock'); const BigNumber = web3.BigNumber; @@ -12,7 +12,7 @@ require('chai') contract('ERC20', function ([_, owner, recipient, anotherAccount]) { beforeEach(async function () { - this.token = await ERC20.new(owner, 100); + this.token = await ERC20Mock.new(owner, 100); }); describe('total supply', function () { diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index 568b7f147..fa733a3f6 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,11 +1,11 @@ const { assertRevert } = require('../../helpers/assertRevert'); -const ERC20Pausable = artifacts.require('ERC20PausableMock'); +const ERC20PausableMock = artifacts.require('ERC20PausableMock'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherAccount, ...otherAccounts]) { beforeEach(async function () { - this.token = await ERC20Pausable.new(pauser, 100, { from: pauser }); + this.token = await ERC20PausableMock.new(pauser, 100, { from: pauser }); }); describe('pauser role', function () { diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index 22c24cd8a..f521bbb75 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -4,7 +4,7 @@ const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); -const ERC721Receiver = artifacts.require('ERC721ReceiverMock.sol'); +const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol'); const BigNumber = web3.BigNumber; require('chai') @@ -237,7 +237,7 @@ function shouldBehaveLikeERC721 ( describe('to a valid receiver contract', function () { beforeEach(async function () { - this.receiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, false); + this.receiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, false); this.toWhom = this.receiver.address; }); @@ -246,7 +246,7 @@ function shouldBehaveLikeERC721 ( it('should call onERC721Received', async function () { const result = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner }); result.receipt.logs.length.should.be.equal(2); - const [log] = decodeLogs([result.receipt.logs[1]], ERC721Receiver, this.receiver.address); + const [log] = decodeLogs([result.receipt.logs[1]], ERC721ReceiverMock, this.receiver.address); log.event.should.be.equal('Received'); log.args.operator.should.be.equal(owner); log.args.from.should.be.equal(owner); @@ -261,7 +261,7 @@ function shouldBehaveLikeERC721 ( result.receipt.logs.length.should.be.equal(2); const [log] = decodeLogs( [result.receipt.logs[1]], - ERC721Receiver, + ERC721ReceiverMock, this.receiver.address ); log.event.should.be.equal('Received'); @@ -297,14 +297,14 @@ function shouldBehaveLikeERC721 ( describe('to a receiver contract returning unexpected value', function () { it('reverts', async function () { - const invalidReceiver = await ERC721Receiver.new('0x42', false); + const invalidReceiver = await ERC721ReceiverMock.new('0x42', false); await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); }); }); describe('to a receiver contract that throws', function () { it('reverts', async function () { - const invalidReceiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, true); + const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true); await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); }); }); diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index 4c40e3972..eef76eba8 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -1,7 +1,7 @@ const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const BigNumber = web3.BigNumber; -const ERC721 = artifacts.require('ERC721Mock.sol'); +const ERC721Mock = artifacts.require('ERC721Mock.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -9,7 +9,7 @@ require('chai') contract('ERC721', function ([_, creator, ...accounts]) { beforeEach(async function () { - this.token = await ERC721.new({ from: creator }); + this.token = await ERC721Mock.new({ from: creator }); }); shouldBehaveLikeERC721(creator, creator, accounts); diff --git a/test/token/ERC721/ERC721Burnable.test.js b/test/token/ERC721/ERC721Burnable.test.js index a8b011b90..745f7dac2 100644 --- a/test/token/ERC721/ERC721Burnable.test.js +++ b/test/token/ERC721/ERC721Burnable.test.js @@ -4,7 +4,7 @@ const { } = require('./ERC721MintBurn.behavior'); const BigNumber = web3.BigNumber; -const ERC721Burnable = artifacts.require('ERC721MintableBurnableImpl.sol'); +const ERC721BurnableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -14,7 +14,7 @@ contract('ERC721Burnable', function ([_, creator, ...accounts]) { const minter = creator; beforeEach(async function () { - this.token = await ERC721Burnable.new({ from: creator }); + this.token = await ERC721BurnableImpl.new({ from: creator }); }); shouldBehaveLikeERC721(creator, minter, accounts); diff --git a/test/token/ERC721/ERC721Mintable.test.js b/test/token/ERC721/ERC721Mintable.test.js index 65c568643..639c8374d 100644 --- a/test/token/ERC721/ERC721Mintable.test.js +++ b/test/token/ERC721/ERC721Mintable.test.js @@ -4,7 +4,7 @@ const { } = require('./ERC721MintBurn.behavior'); const BigNumber = web3.BigNumber; -const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol'); +const ERC721MintableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -14,7 +14,7 @@ contract('ERC721Mintable', function ([_, creator, ...accounts]) { const minter = creator; beforeEach(async function () { - this.token = await ERC721Mintable.new({ + this.token = await ERC721MintableImpl.new({ from: creator, }); }); diff --git a/test/token/ERC721/ERC721Pausable.test.js b/test/token/ERC721/ERC721Pausable.test.js index 3724655e0..3961368ef 100644 --- a/test/token/ERC721/ERC721Pausable.test.js +++ b/test/token/ERC721/ERC721Pausable.test.js @@ -3,7 +3,7 @@ const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); const BigNumber = web3.BigNumber; -const ERC721Pausable = artifacts.require('ERC721PausableMock.sol'); +const ERC721PausableMock = artifacts.require('ERC721PausableMock.sol'); require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -18,7 +18,7 @@ contract('ERC721Pausable', function ([ ...accounts ]) { beforeEach(async function () { - this.token = await ERC721Pausable.new({ from: creator }); + this.token = await ERC721PausableMock.new({ from: creator }); }); describe('pauser role', function () { From e7aa8dedbcd4d9e1d737ee430014ddb6cc0b052a Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 19 Sep 2018 19:59:13 -0300 Subject: [PATCH 097/205] Turn off blank-lines Solium rule (#1284) * turn off blank-lines rule * remove triple newlines (cherry picked from commit 9b3710465583284b8c4c5d2245749246bb2e0094) --- .soliumrc.json | 1 + contracts/access/Roles.sol | 1 - contracts/access/roles/CapperRole.sol | 1 - contracts/access/roles/MinterRole.sol | 1 - contracts/access/roles/PauserRole.sol | 1 - contracts/access/roles/SignerRole.sol | 1 - contracts/crowdsale/Crowdsale.sol | 1 - contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 1 - contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol | 1 - contracts/crowdsale/distribution/RefundableCrowdsale.sol | 2 -- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 1 - contracts/crowdsale/emission/MintedCrowdsale.sol | 1 - contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 1 - contracts/crowdsale/validation/CappedCrowdsale.sol | 1 - contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol | 1 - contracts/crowdsale/validation/TimedCrowdsale.sol | 1 - contracts/cryptography/ECDSA.sol | 1 - contracts/cryptography/MerkleProof.sol | 1 - contracts/drafts/BreakInvariantBounty.sol | 3 --- contracts/drafts/Counter.sol | 1 - contracts/drafts/ERC1046/TokenMetadata.sol | 2 -- contracts/drafts/ERC20Migrator.sol | 1 - contracts/drafts/SignatureBouncer.sol | 1 - contracts/drafts/TokenVesting.sol | 1 - contracts/examples/SampleCrowdsale.sol | 2 -- contracts/examples/SimpleToken.sol | 2 -- contracts/introspection/ERC165.sol | 1 - contracts/introspection/ERC165Checker.sol | 2 -- contracts/introspection/IERC165.sol | 1 - contracts/lifecycle/Pausable.sol | 2 -- contracts/math/Math.sol | 1 - contracts/math/SafeMath.sol | 1 - contracts/mocks/AddressImpl.sol | 1 - contracts/mocks/AllowanceCrowdsaleImpl.sol | 1 - contracts/mocks/CappedCrowdsaleImpl.sol | 1 - contracts/mocks/CapperRoleMock.sol | 1 - contracts/mocks/ConditionalEscrowMock.sol | 2 -- contracts/mocks/CounterImpl.sol | 1 - contracts/mocks/DetailedERC20Mock.sol | 1 - contracts/mocks/ECDSAMock.sol | 2 -- contracts/mocks/ERC165/ERC165InterfacesSupported.sol | 3 --- contracts/mocks/ERC165/ERC165NotSupported.sol | 1 - contracts/mocks/ERC165CheckerMock.sol | 1 - contracts/mocks/ERC165Mock.sol | 1 - contracts/mocks/ERC20BurnableMock.sol | 1 - contracts/mocks/ERC20MintableMock.sol | 1 - contracts/mocks/ERC20Mock.sol | 1 - contracts/mocks/ERC20PausableMock.sol | 1 - contracts/mocks/ERC20WithMetadataMock.sol | 1 - contracts/mocks/ERC721FullMock.sol | 1 - contracts/mocks/ERC721MintableBurnableImpl.sol | 1 - contracts/mocks/ERC721Mock.sol | 1 - contracts/mocks/ERC721PausableMock.sol | 1 - contracts/mocks/ERC721ReceiverMock.sol | 1 - contracts/mocks/FinalizableCrowdsaleImpl.sol | 1 - contracts/mocks/IncreasingPriceCrowdsaleImpl.sol | 1 - contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol | 1 - contracts/mocks/MathMock.sol | 2 -- contracts/mocks/MerkleProofWrapper.sol | 1 - contracts/mocks/MintedCrowdsaleImpl.sol | 1 - contracts/mocks/MinterRoleMock.sol | 1 - contracts/mocks/PausableMock.sol | 2 -- contracts/mocks/PauserRoleMock.sol | 1 - contracts/mocks/PostDeliveryCrowdsaleImpl.sol | 1 - contracts/mocks/PullPaymentMock.sol | 2 -- contracts/mocks/ReentrancyAttack.sol | 1 - contracts/mocks/ReentrancyMock.sol | 1 - contracts/mocks/RefundableCrowdsaleImpl.sol | 1 - contracts/mocks/RolesMock.sol | 1 - contracts/mocks/SafeERC20Helper.sol | 3 --- contracts/mocks/SafeMathMock.sol | 2 -- contracts/mocks/SecondaryMock.sol | 1 - contracts/mocks/SignatureBouncerMock.sol | 1 - contracts/mocks/SignerRoleMock.sol | 1 - contracts/mocks/TimedCrowdsaleImpl.sol | 1 - contracts/ownership/Ownable.sol | 2 -- contracts/ownership/Secondary.sol | 1 - contracts/payment/ConditionalEscrow.sol | 1 - contracts/payment/Escrow.sol | 1 - contracts/payment/PullPayment.sol | 1 - contracts/payment/RefundEscrow.sol | 1 - contracts/payment/SplitPayment.sol | 1 - contracts/token/ERC20/ERC20.sol | 1 - contracts/token/ERC20/ERC20Burnable.sol | 1 - contracts/token/ERC20/ERC20Capped.sol | 1 - contracts/token/ERC20/ERC20Detailed.sol | 1 - contracts/token/ERC20/ERC20Mintable.sol | 1 - contracts/token/ERC20/ERC20Pausable.sol | 1 - contracts/token/ERC20/IERC20.sol | 1 - contracts/token/ERC20/SafeERC20.sol | 1 - contracts/token/ERC20/TokenTimelock.sol | 1 - contracts/token/ERC721/ERC721.sol | 1 - contracts/token/ERC721/ERC721Burnable.sol | 1 - contracts/token/ERC721/ERC721Enumerable.sol | 1 - contracts/token/ERC721/ERC721Full.sol | 1 - contracts/token/ERC721/ERC721Holder.sol | 1 - contracts/token/ERC721/ERC721Metadata.sol | 1 - contracts/token/ERC721/ERC721Mintable.sol | 1 - contracts/token/ERC721/ERC721Pausable.sol | 1 - contracts/token/ERC721/IERC721.sol | 1 - contracts/token/ERC721/IERC721Enumerable.sol | 1 - contracts/token/ERC721/IERC721Full.sol | 1 - contracts/token/ERC721/IERC721Metadata.sol | 1 - contracts/token/ERC721/IERC721Receiver.sol | 1 - contracts/utils/Address.sol | 1 - contracts/utils/ReentrancyGuard.sol | 1 - 106 files changed, 1 insertion(+), 124 deletions(-) diff --git a/.soliumrc.json b/.soliumrc.json index be4afce10..8fe25b30e 100644 --- a/.soliumrc.json +++ b/.soliumrc.json @@ -2,6 +2,7 @@ "extends": "solium:all", "plugins": ["security"], "rules": { + "blank-lines": "off", "error-reason": "off", "indentation": ["error", 2], "lbrace": "off", diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index b0212c2be..930a62066 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Roles * @dev Library for managing addresses assigned to a Role. diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index 1aa2770d9..a79e8e694 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract CapperRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index 279f4ce00..d908e3004 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract MinterRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index 2c89cec55..d59839d6b 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract PauserRole { using Roles for Roles.Role; diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index 5563c46f0..bbf8fd36f 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../Roles.sol"; - contract SignerRole { using Roles for Roles.Role; diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index dd036a352..c1302ede4 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -4,7 +4,6 @@ import "../token/ERC20/IERC20.sol"; import "../math/SafeMath.sol"; import "../token/ERC20/SafeERC20.sol"; - /** * @title Crowdsale * @dev Crowdsale is a base contract for managing a token crowdsale, diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index c6995a44d..37d205c8e 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../validation/TimedCrowdsale.sol"; - /** * @title FinalizableCrowdsale * @dev Extension of Crowdsale with a one-off finalization action, where one diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index 5a7d89c7e..da9392aed 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -4,7 +4,6 @@ import "../validation/TimedCrowdsale.sol"; import "../../token/ERC20/IERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title PostDeliveryCrowdsale * @dev Crowdsale that locks tokens from withdrawal until it ends. diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index 80db88d41..a69d4a0ed 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -1,11 +1,9 @@ pragma solidity ^0.4.24; - import "../../math/SafeMath.sol"; import "./FinalizableCrowdsale.sol"; import "../../payment/RefundEscrow.sol"; - /** * @title RefundableCrowdsale * @dev Extension of Crowdsale contract that adds a funding goal, and diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index 2af6752fb..736635e0b 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -5,7 +5,6 @@ import "../../token/ERC20/IERC20.sol"; import "../../token/ERC20/SafeERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title AllowanceCrowdsale * @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale. diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index a57c7b807..62b03189a 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../Crowdsale.sol"; import "../../token/ERC20/ERC20Mintable.sol"; - /** * @title MintedCrowdsale * @dev Extension of Crowdsale contract whose tokens are minted in each purchase. diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 2d07c6763..386c6202b 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../validation/TimedCrowdsale.sol"; import "../../math/SafeMath.sol"; - /** * @title IncreasingPriceCrowdsale * @dev Extension of Crowdsale contract that increases the price of tokens linearly in time. diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 67a7d7c92..21708c34a 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; - /** * @title CappedCrowdsale * @dev Crowdsale with a limit for total contributions. diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index d2033984f..d00cb602e 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -4,7 +4,6 @@ import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; import "../../access/roles/CapperRole.sol"; - /** * @title IndividuallyCappedCrowdsale * @dev Crowdsale with per-beneficiary caps. diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index abbf1d116..098112cae 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; - /** * @title TimedCrowdsale * @dev Crowdsale accepting contributions only within a time frame. diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 61d19f20c..3f0ad1bd2 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Elliptic curve signature operations * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d diff --git a/contracts/cryptography/MerkleProof.sol b/contracts/cryptography/MerkleProof.sol index d490e7ff5..a0c304c57 100644 --- a/contracts/cryptography/MerkleProof.sol +++ b/contracts/cryptography/MerkleProof.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title MerkleProof * @dev Merkle proof verification based on diff --git a/contracts/drafts/BreakInvariantBounty.sol b/contracts/drafts/BreakInvariantBounty.sol index 901ade023..6dec45a3b 100644 --- a/contracts/drafts/BreakInvariantBounty.sol +++ b/contracts/drafts/BreakInvariantBounty.sol @@ -1,10 +1,8 @@ pragma solidity ^0.4.24; - import "../payment/PullPayment.sol"; import "../ownership/Ownable.sol"; - /** * @title BreakInvariantBounty * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. @@ -79,7 +77,6 @@ contract BreakInvariantBounty is PullPayment, Ownable { } - /** * @title Target * @dev Your main contract should inherit from this class and implement the checkInvariant method. diff --git a/contracts/drafts/Counter.sol b/contracts/drafts/Counter.sol index b47d9b824..3557bd744 100644 --- a/contracts/drafts/Counter.sol +++ b/contracts/drafts/Counter.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Counter * @author Matt Condon (@shrugs) diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index a85dac1f3..85b6ec671 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../token/ERC20/IERC20.sol"; - /** * @title ERC-1047 Token Metadata * @dev See https://eips.ethereum.org/EIPS/eip-1046 @@ -13,7 +12,6 @@ contract ERC20TokenMetadata is IERC20 { function tokenURI() external view returns (string); } - contract ERC20WithMetadata is ERC20TokenMetadata { string private _tokenURI = ""; diff --git a/contracts/drafts/ERC20Migrator.sol b/contracts/drafts/ERC20Migrator.sol index 69e745f14..44ed16423 100644 --- a/contracts/drafts/ERC20Migrator.sol +++ b/contracts/drafts/ERC20Migrator.sol @@ -5,7 +5,6 @@ import "../token/ERC20/ERC20Mintable.sol"; import "../token/ERC20/SafeERC20.sol"; import "../math/Math.sol"; - /** * @title ERC20Migrator * @dev This contract can be used to migrate an ERC20 token from one diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index a584b7aad..ff596b006 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../access/roles/SignerRole.sol"; import "../cryptography/ECDSA.sol"; - /** * @title SignatureBouncer * @author PhABC, Shrugs and aflesher diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 75b2aaa66..b97b60b2b 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -6,7 +6,6 @@ import "../token/ERC20/SafeERC20.sol"; import "../ownership/Ownable.sol"; import "../math/SafeMath.sol"; - /** * @title TokenVesting * @dev A token holder contract that can release its token balance gradually like a diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 293a9e438..6e1272223 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -5,7 +5,6 @@ import "../crowdsale/distribution/RefundableCrowdsale.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; import "../token/ERC20/ERC20Mintable.sol"; - /** * @title SampleCrowdsaleToken * @dev Very simple ERC20 Token that can be minted. @@ -18,7 +17,6 @@ contract SampleCrowdsaleToken is ERC20Mintable { uint8 public constant decimals = 18; } - /** * @title SampleCrowdsale * @dev This is an example of a fully fledged crowdsale. diff --git a/contracts/examples/SimpleToken.sol b/contracts/examples/SimpleToken.sol index 67de00ca4..8c63fdd98 100644 --- a/contracts/examples/SimpleToken.sol +++ b/contracts/examples/SimpleToken.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../token/ERC20/ERC20.sol"; - /** * @title SimpleToken * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 849cdf0c1..1af78d111 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC165.sol"; - /** * @title ERC165 * @author Matt Condon (@shrugs) diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 36bc20959..3491df904 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC165Checker * @dev Use `using ERC165Checker for address`; to include this library @@ -16,7 +15,6 @@ library ERC165Checker { * bytes4(keccak256('supportsInterface(bytes4)')) */ - /** * @notice Query if a contract supports ERC165 * @param account The address of the contract to query for support of ERC165 diff --git a/contracts/introspection/IERC165.sol b/contracts/introspection/IERC165.sol index 4d8b5b69f..4e4b7bbf6 100644 --- a/contracts/introspection/IERC165.sol +++ b/contracts/introspection/IERC165.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title IERC165 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 6d5aec994..5287ecdcb 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/PauserRole.sol"; - /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. @@ -13,7 +12,6 @@ contract Pausable is PauserRole { bool private _paused = false; - /** * @return true if the contract is paused, false otherwise. */ diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index 78ef1ae2b..d51a720c9 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Math * @dev Assorted math operations diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index d183fa361..97494e1f1 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title SafeMath * @dev Math operations with safety checks that revert on error diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol index b46fd06c3..e29396056 100644 --- a/contracts/mocks/AddressImpl.sol +++ b/contracts/mocks/AddressImpl.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../utils/Address.sol"; - contract AddressImpl { function isContract(address account) external diff --git a/contracts/mocks/AllowanceCrowdsaleImpl.sol b/contracts/mocks/AllowanceCrowdsaleImpl.sol index be01ccdf9..5b2104e38 100644 --- a/contracts/mocks/AllowanceCrowdsaleImpl.sol +++ b/contracts/mocks/AllowanceCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/emission/AllowanceCrowdsale.sol"; - contract AllowanceCrowdsaleImpl is AllowanceCrowdsale { constructor ( diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index e92cec204..176033b7f 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/CappedCrowdsale.sol"; - contract CappedCrowdsaleImpl is CappedCrowdsale { constructor ( diff --git a/contracts/mocks/CapperRoleMock.sol b/contracts/mocks/CapperRoleMock.sol index 05c15c9dd..118058f39 100644 --- a/contracts/mocks/CapperRoleMock.sol +++ b/contracts/mocks/CapperRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/CapperRole.sol"; - contract CapperRoleMock is CapperRole { function removeCapper(address account) public { _removeCapper(account); diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index d3723ad7d..93a594b97 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../payment/ConditionalEscrow.sol"; - // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { mapping(address => bool) private _allowed; diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol index d42fcbda2..3c958ba97 100644 --- a/contracts/mocks/CounterImpl.sol +++ b/contracts/mocks/CounterImpl.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../drafts/Counter.sol"; - contract CounterImpl { using Counter for Counter.Counter; diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index 082c451be..eea706326 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; - contract ERC20DetailedMock is ERC20, ERC20Detailed { constructor( string name, diff --git a/contracts/mocks/ECDSAMock.sol b/contracts/mocks/ECDSAMock.sol index fa3f22348..9f489069f 100644 --- a/contracts/mocks/ECDSAMock.sol +++ b/contracts/mocks/ECDSAMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../cryptography/ECDSA.sol"; - contract ECDSAMock { using ECDSA for bytes32; diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 6573d972c..1a06e9d52 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../introspection/IERC165.sol"; - /** * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md#specification * > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead throw an exception. @@ -56,8 +55,6 @@ contract SupportsInterfaceWithLookupMock is IERC165 { } } - - contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock { constructor (bytes4[] interfaceIds) public diff --git a/contracts/mocks/ERC165/ERC165NotSupported.sol b/contracts/mocks/ERC165/ERC165NotSupported.sol index 763f8faba..156ef8e8b 100644 --- a/contracts/mocks/ERC165/ERC165NotSupported.sol +++ b/contracts/mocks/ERC165/ERC165NotSupported.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - contract ERC165NotSupported { } diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index f4d6219f9..b0728ba15 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../introspection/ERC165Checker.sol"; - contract ERC165CheckerMock { using ERC165Checker for address; diff --git a/contracts/mocks/ERC165Mock.sol b/contracts/mocks/ERC165Mock.sol index cbedcdb74..c42ba62f2 100644 --- a/contracts/mocks/ERC165Mock.sol +++ b/contracts/mocks/ERC165Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../introspection/ERC165.sol"; - contract ERC165Mock is ERC165 { function registerInterface(bytes4 interfaceId) public diff --git a/contracts/mocks/ERC20BurnableMock.sol b/contracts/mocks/ERC20BurnableMock.sol index bbc7c4d1a..2c8b3b54a 100644 --- a/contracts/mocks/ERC20BurnableMock.sol +++ b/contracts/mocks/ERC20BurnableMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Burnable.sol"; - contract ERC20BurnableMock is ERC20Burnable { constructor(address initialAccount, uint256 initialBalance) public { diff --git a/contracts/mocks/ERC20MintableMock.sol b/contracts/mocks/ERC20MintableMock.sol index a2056548f..31384c790 100644 --- a/contracts/mocks/ERC20MintableMock.sol +++ b/contracts/mocks/ERC20MintableMock.sol @@ -3,6 +3,5 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "./MinterRoleMock.sol"; - contract ERC20MintableMock is ERC20Mintable, MinterRoleMock { } diff --git a/contracts/mocks/ERC20Mock.sol b/contracts/mocks/ERC20Mock.sol index 046730750..ab0877653 100644 --- a/contracts/mocks/ERC20Mock.sol +++ b/contracts/mocks/ERC20Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; - // mock class using ERC20 contract ERC20Mock is ERC20 { diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index c4aa05d06..c6c0fd5ed 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Pausable.sol"; import "./PauserRoleMock.sol"; - // mock class using ERC20Pausable contract ERC20PausableMock is ERC20Pausable, PauserRoleMock { diff --git a/contracts/mocks/ERC20WithMetadataMock.sol b/contracts/mocks/ERC20WithMetadataMock.sol index cdc1fe365..ec2d122a1 100644 --- a/contracts/mocks/ERC20WithMetadataMock.sol +++ b/contracts/mocks/ERC20WithMetadataMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; import "../drafts/ERC1046/TokenMetadata.sol"; - contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { constructor(string tokenURI) public ERC20WithMetadata(tokenURI) diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index 49f4e31b7..2d85e7372 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -5,7 +5,6 @@ import "../token/ERC721/ERC721Mintable.sol"; import "../token/ERC721/ERC721MetadataMintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; - /** * @title ERC721FullMock * This mock just provides a public mint and burn functions for testing purposes, diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index eb328afa2..51d3ff4f6 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -5,7 +5,6 @@ import "../token/ERC721/ERC721Mintable.sol"; import "../token/ERC721/ERC721MetadataMintable.sol"; import "../token/ERC721/ERC721Burnable.sol"; - /** * @title ERC721MintableBurnableImpl */ diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index 607ceed13..514d3bdbe 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721.sol"; - /** * @title ERC721Mock * This mock just provides a public mint and burn functions for testing purposes diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index 0efcbb925..9751d04cb 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/ERC721Pausable.sol"; import "./PauserRoleMock.sol"; - /** * @title ERC721PausableMock * This mock just provides a public mint, burn and exists functions for testing purposes diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 4e21ff6ac..57fb04e3a 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../token/ERC721/IERC721Receiver.sol"; - contract ERC721ReceiverMock is IERC721Receiver { bytes4 private _retval; bool private _reverts; diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 20076bdd1..084780b1d 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/FinalizableCrowdsale.sol"; - contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { constructor ( diff --git a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol index 29d71ec8a..6f1f2e2a0 100644 --- a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol +++ b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../crowdsale/price/IncreasingPriceCrowdsale.sol"; import "../math/SafeMath.sol"; - contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale { constructor ( diff --git a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol index d47600f8d..1bcb95301 100644 --- a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol +++ b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol @@ -4,7 +4,6 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol"; import "./CapperRoleMock.sol"; - contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock { diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index 696653858..72f7fc204 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../math/Math.sol"; - contract MathMock { function max(uint256 a, uint256 b) public pure returns (uint256) { return Math.max(a, b); diff --git a/contracts/mocks/MerkleProofWrapper.sol b/contracts/mocks/MerkleProofWrapper.sol index 7909098f6..b359dc790 100644 --- a/contracts/mocks/MerkleProofWrapper.sol +++ b/contracts/mocks/MerkleProofWrapper.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import { MerkleProof } from "../cryptography/MerkleProof.sol"; - contract MerkleProofWrapper { function verify( diff --git a/contracts/mocks/MintedCrowdsaleImpl.sol b/contracts/mocks/MintedCrowdsaleImpl.sol index afdd3b8c7..518371b75 100644 --- a/contracts/mocks/MintedCrowdsaleImpl.sol +++ b/contracts/mocks/MintedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; - contract MintedCrowdsaleImpl is MintedCrowdsale { constructor ( diff --git a/contracts/mocks/MinterRoleMock.sol b/contracts/mocks/MinterRoleMock.sol index bedf3d45f..45e5a4195 100644 --- a/contracts/mocks/MinterRoleMock.sol +++ b/contracts/mocks/MinterRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/MinterRole.sol"; - contract MinterRoleMock is MinterRole { function removeMinter(address account) public { _removeMinter(account); diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index a1c24c087..72ec843ed 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -1,10 +1,8 @@ pragma solidity ^0.4.24; - import "../lifecycle/Pausable.sol"; import "./PauserRoleMock.sol"; - // mock class using Pausable contract PausableMock is Pausable, PauserRoleMock { bool public drasticMeasureTaken; diff --git a/contracts/mocks/PauserRoleMock.sol b/contracts/mocks/PauserRoleMock.sol index df0213326..267101e4a 100644 --- a/contracts/mocks/PauserRoleMock.sol +++ b/contracts/mocks/PauserRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/PauserRole.sol"; - contract PauserRoleMock is PauserRole { function removePauser(address account) public { _removePauser(account); diff --git a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol index c6dca89a5..98d056c66 100644 --- a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/PostDeliveryCrowdsale.sol"; - contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale { constructor ( diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index d6da3ed70..63076c904 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../payment/PullPayment.sol"; - // mock class using PullPayment contract PullPaymentMock is PullPayment { diff --git a/contracts/mocks/ReentrancyAttack.sol b/contracts/mocks/ReentrancyAttack.sol index 05ef748e7..96231de27 100644 --- a/contracts/mocks/ReentrancyAttack.sol +++ b/contracts/mocks/ReentrancyAttack.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - contract ReentrancyAttack { function callSender(bytes4 data) public { diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index 130a8fd90..474ecd433 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../utils/ReentrancyGuard.sol"; import "./ReentrancyAttack.sol"; - contract ReentrancyMock is ReentrancyGuard { uint256 public counter; diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index 631f29d04..a14dfbcb3 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; - contract RefundableCrowdsaleImpl is RefundableCrowdsale { constructor ( diff --git a/contracts/mocks/RolesMock.sol b/contracts/mocks/RolesMock.sol index cd2922289..bfcee20ee 100644 --- a/contracts/mocks/RolesMock.sol +++ b/contracts/mocks/RolesMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/Roles.sol"; - contract RolesMock { using Roles for Roles.Role; diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 0009fd01c..c80c762d9 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; - contract ERC20FailingMock is IERC20 { function totalSupply() public view returns (uint256) { return 0; @@ -30,7 +29,6 @@ contract ERC20FailingMock is IERC20 { } } - contract ERC20SucceedingMock is IERC20 { function totalSupply() public view returns (uint256) { return 0; @@ -57,7 +55,6 @@ contract ERC20SucceedingMock is IERC20 { } } - contract SafeERC20Helper { using SafeERC20 for IERC20; diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index c5464ec16..7ddf17e9f 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -1,9 +1,7 @@ pragma solidity ^0.4.24; - import "../math/SafeMath.sol"; - contract SafeMathMock { function mul(uint256 a, uint256 b) public pure returns (uint256) { diff --git a/contracts/mocks/SecondaryMock.sol b/contracts/mocks/SecondaryMock.sol index 6863112fa..268c12516 100644 --- a/contracts/mocks/SecondaryMock.sol +++ b/contracts/mocks/SecondaryMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../ownership/Secondary.sol"; - contract SecondaryMock is Secondary { function onlyPrimaryMock() public view onlyPrimary { } diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index 67a39636e..85076eae6 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../drafts/SignatureBouncer.sol"; import "./SignerRoleMock.sol"; - contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { function checkValidSignature(address account, bytes signature) public diff --git a/contracts/mocks/SignerRoleMock.sol b/contracts/mocks/SignerRoleMock.sol index ba71cdeaa..faf92db68 100644 --- a/contracts/mocks/SignerRoleMock.sol +++ b/contracts/mocks/SignerRoleMock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../access/roles/SignerRole.sol"; - contract SignerRoleMock is SignerRole { function removeSigner(address account) public { _removeSigner(account); diff --git a/contracts/mocks/TimedCrowdsaleImpl.sol b/contracts/mocks/TimedCrowdsaleImpl.sol index 296484ed1..f16e5eb2a 100644 --- a/contracts/mocks/TimedCrowdsaleImpl.sol +++ b/contracts/mocks/TimedCrowdsaleImpl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/TimedCrowdsale.sol"; - contract TimedCrowdsaleImpl is TimedCrowdsale { constructor ( diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 742321b50..5279d5d42 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control @@ -14,7 +13,6 @@ contract Ownable { address indexed newOwner ); - /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index 055db51d5..d602d67ec 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Secondary * @dev A Secondary contract can only be used by its primary account (the one that created it) diff --git a/contracts/payment/ConditionalEscrow.sol b/contracts/payment/ConditionalEscrow.sol index 933243a25..645dad479 100644 --- a/contracts/payment/ConditionalEscrow.sol +++ b/contracts/payment/ConditionalEscrow.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./Escrow.sol"; - /** * @title ConditionalEscrow * @dev Base abstract escrow to only allow withdrawal if a condition is met. diff --git a/contracts/payment/Escrow.sol b/contracts/payment/Escrow.sol index 78dda09f9..7fb118e3a 100644 --- a/contracts/payment/Escrow.sol +++ b/contracts/payment/Escrow.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; import "../ownership/Secondary.sol"; - /** * @title Escrow * @dev Base escrow contract, holds funds destinated to a payee until they diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 8399fa4e1..67ef8c667 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./Escrow.sol"; - /** * @title PullPayment * @dev Base contract supporting async send for pull payments. Inherit from this diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/RefundEscrow.sol index acad2ba3c..c3770dbbb 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/RefundEscrow.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ConditionalEscrow.sol"; - /** * @title RefundEscrow * @dev Escrow that holds funds for a beneficiary, deposited from multiple parties. diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index c7bc9bfff..8bfcc7690 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; - /** * @title SplitPayment * @dev This contract can be used when payments need to be received by a group diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 09049c59a..3d18c1dec 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./IERC20.sol"; import "../../math/SafeMath.sol"; - /** * @title Standard ERC20 token * diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index 658068d87..ba4a2ccbe 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; - /** * @title Burnable Token * @dev Token that can be irreversibly burned (destroyed). diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 1222034cd..0a73159b6 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC20Mintable.sol"; - /** * @title Capped token * @dev Mintable token with a token cap. diff --git a/contracts/token/ERC20/ERC20Detailed.sol b/contracts/token/ERC20/ERC20Detailed.sol index ba411aa1f..706dbfc46 100644 --- a/contracts/token/ERC20/ERC20Detailed.sol +++ b/contracts/token/ERC20/ERC20Detailed.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC20.sol"; - /** * @title ERC20Detailed token * @dev The decimals are only for visualization purposes. diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index 7f9787b13..386abf64d 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "../../access/roles/MinterRole.sol"; - /** * @title ERC20Mintable * @dev ERC20 minting logic diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index 32932355d..8e6aa881f 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "../../lifecycle/Pausable.sol"; - /** * @title Pausable token * @dev ERC20 modified with pausable transfers. diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index 34d68fd62..37e5a447c 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 48b15fba9..10c6ff2bc 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC20.sol"; import "./IERC20.sol"; - /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure. diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index 9989ce77a..55903482b 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./SafeERC20.sol"; - /** * @title TokenTimelock * @dev TokenTimelock is a token holder contract that will allow a diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 7501248d7..eeee146e2 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -6,7 +6,6 @@ import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; import "../../introspection/ERC165.sol"; - /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index 3195cd424..3fc0277e5 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; - contract ERC721Burnable is ERC721 { function burn(uint256 tokenId) public diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index a4cceed20..0a2797eed 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -4,7 +4,6 @@ import "./IERC721Enumerable.sol"; import "./ERC721.sol"; import "../../introspection/ERC165.sol"; - contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; diff --git a/contracts/token/ERC721/ERC721Full.sol b/contracts/token/ERC721/ERC721Full.sol index 6492a8ca1..293637501 100644 --- a/contracts/token/ERC721/ERC721Full.sol +++ b/contracts/token/ERC721/ERC721Full.sol @@ -4,7 +4,6 @@ import "./ERC721.sol"; import "./ERC721Enumerable.sol"; import "./ERC721Metadata.sol"; - /** * @title Full ERC721 Token * This implementation includes all the required and some optional functionality of the ERC721 standard diff --git a/contracts/token/ERC721/ERC721Holder.sol b/contracts/token/ERC721/ERC721Holder.sol index 67048598f..cf0e9ce55 100644 --- a/contracts/token/ERC721/ERC721Holder.sol +++ b/contracts/token/ERC721/ERC721Holder.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721Receiver.sol"; - contract ERC721Holder is IERC721Receiver { function onERC721Received( address, diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index b4f1da3ab..8334160aa 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -4,7 +4,6 @@ import "./ERC721.sol"; import "./IERC721Metadata.sol"; import "../../introspection/ERC165.sol"; - contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name string internal _name; diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index b7928a903..74b7b0186 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; import "../../access/roles/MinterRole.sol"; - /** * @title ERC721Mintable * @dev ERC721 minting logic diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/ERC721Pausable.sol index c0cca9dcf..c66d9da1f 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/ERC721Pausable.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; import "../../lifecycle/Pausable.sol"; - /** * @title ERC721 Non-Fungible Pausable token * @dev ERC721 modified with pausable transfers. diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index 1d4ac1de4..24bc6a242 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "../../introspection/IERC165.sol"; - /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Enumerable.sol b/contracts/token/ERC721/IERC721Enumerable.sol index b848b7b69..b772f2507 100644 --- a/contracts/token/ERC721/IERC721Enumerable.sol +++ b/contracts/token/ERC721/IERC721Enumerable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Full.sol b/contracts/token/ERC721/IERC721Full.sol index 10914dc23..90d8c21d8 100644 --- a/contracts/token/ERC721/IERC721Full.sol +++ b/contracts/token/ERC721/IERC721Full.sol @@ -4,7 +4,6 @@ import "./IERC721.sol"; import "./IERC721Enumerable.sol"; import "./IERC721Metadata.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, full implementation interface * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index ed7ab29d9..2e1521208 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -2,7 +2,6 @@ pragma solidity ^0.4.24; import "./IERC721.sol"; - /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol index 946582f7e..e692f7e2c 100644 --- a/contracts/token/ERC721/IERC721Receiver.sol +++ b/contracts/token/ERC721/IERC721Receiver.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index 1f27c93f1..92a43ff9c 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * Utility library of inline functions on addresses */ diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 7f232cce5..63da3a99e 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -1,6 +1,5 @@ pragma solidity ^0.4.24; - /** * @title Helps contracts guard against reentrancy attacks. * @author Remco Bloemen , Eenae From 62ed8e2fe47f1ed2cee4c793613c1652a261ae63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:21:24 -0300 Subject: [PATCH 098/205] Removed BreakInvariantBounty. (#1424) (cherry picked from commit 9be0f100c48e4726bee73829fbb10f7d85b6ef54) --- contracts/drafts/BreakInvariantBounty.sol | 93 ------------- contracts/mocks/BreakInvariantBountyMock.sol | 29 ---- test/drafts/BreakInvariantBounty.test.js | 134 ------------------- 3 files changed, 256 deletions(-) delete mode 100644 contracts/drafts/BreakInvariantBounty.sol delete mode 100644 contracts/mocks/BreakInvariantBountyMock.sol delete mode 100644 test/drafts/BreakInvariantBounty.test.js diff --git a/contracts/drafts/BreakInvariantBounty.sol b/contracts/drafts/BreakInvariantBounty.sol deleted file mode 100644 index 6dec45a3b..000000000 --- a/contracts/drafts/BreakInvariantBounty.sol +++ /dev/null @@ -1,93 +0,0 @@ -pragma solidity ^0.4.24; - -import "../payment/PullPayment.sol"; -import "../ownership/Ownable.sol"; - -/** - * @title BreakInvariantBounty - * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. - */ -contract BreakInvariantBounty is PullPayment, Ownable { - bool private _claimable; - mapping(address => address) private _researchers; - - event TargetCreated(address createdAddress); - event BountyCanceled(); - - constructor() public { - _claimable = true; - } - - /** - * @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed. - */ - function() external payable { - require(_claimable); - } - - /** - * @dev Determine if the bounty is claimable. - * @return false if the bounty was claimed, true otherwise. - */ - function claimable() public view returns(bool) { - return _claimable; - } - - /** - * @dev Create and deploy the target contract (extension of Target contract), and sets the - * msg.sender as a researcher - * @return A target contract - */ - function createTarget() public returns(Target) { - Target target = Target(_deployContract()); - _researchers[target] = msg.sender; - emit TargetCreated(target); - return target; - } - - /** - * @dev Transfers the contract funds to the researcher that proved the contract is broken. - * @param target contract - */ - function claim(Target target) public { - require(_claimable); - address researcher = _researchers[target]; - require(researcher != address(0)); - // Check Target contract invariants - require(!target.checkInvariant()); - _asyncTransfer(researcher, address(this).balance); - _claimable = false; - } - - /** - * @dev Cancels the bounty and transfers all funds to the owner - */ - function cancelBounty() public onlyOwner{ - require(_claimable); - _asyncTransfer(owner(), address(this).balance); - _claimable = false; - emit BountyCanceled(); - } - - /** - * @dev Internal function to deploy the target contract. - * @return A target contract address - */ - function _deployContract() internal returns(address); - -} - -/** - * @title Target - * @dev Your main contract should inherit from this class and implement the checkInvariant method. - */ -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. - */ - function checkInvariant() public returns(bool); -} diff --git a/contracts/mocks/BreakInvariantBountyMock.sol b/contracts/mocks/BreakInvariantBountyMock.sol deleted file mode 100644 index af3e60c57..000000000 --- a/contracts/mocks/BreakInvariantBountyMock.sol +++ /dev/null @@ -1,29 +0,0 @@ -pragma solidity ^0.4.24; - -// When this line is split, truffle parsing fails. -// See: https://github.com/ethereum/solidity/issues/4871 -// solium-disable-next-line max-len -import {BreakInvariantBounty, Target} from "../drafts/BreakInvariantBounty.sol"; - - -contract TargetMock is Target { - bool private exploited; - - function exploitVulnerability() public { - exploited = true; - } - - function checkInvariant() public returns (bool) { - if (exploited) { - return false; - } - - return true; - } -} - -contract BreakInvariantBountyMock is BreakInvariantBounty { - function _deployContract() internal returns (address) { - return new TargetMock(); - } -} diff --git a/test/drafts/BreakInvariantBounty.test.js b/test/drafts/BreakInvariantBounty.test.js deleted file mode 100644 index b9b97054d..000000000 --- a/test/drafts/BreakInvariantBounty.test.js +++ /dev/null @@ -1,134 +0,0 @@ -const { ethGetBalance, ethSendTransaction } = require('./helpers/web3'); -const { ether } = require('./helpers/ether'); -const { balanceDifference } = require('./helpers/balanceDiff'); -const expectEvent = require('./helpers/expectEvent'); -const { assertRevert } = require('./helpers/assertRevert'); - -const BreakInvariantBountyMock = artifacts.require('BreakInvariantBountyMock'); -const TargetMock = artifacts.require('TargetMock'); - -require('chai') - .use(require('chai-bignumber')(web3.BigNumber)) - .should(); - -const reward = ether(1); - -contract('BreakInvariantBounty', function ([_, owner, researcher, anyone, nonTarget]) { - beforeEach(async function () { - this.bounty = await BreakInvariantBountyMock.new({ from: owner }); - }); - - it('can set reward', async function () { - await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(reward); - }); - - context('with reward', function () { - beforeEach(async function () { - await ethSendTransaction({ from: owner, to: this.bounty.address, value: reward }); - }); - - describe('claim', function () { - it('is initially claimable', async function () { - (await this.bounty.claimable()).should.equal(true); - }); - - it('can create claimable target', async function () { - const { logs } = await this.bounty.createTarget({ from: researcher }); - expectEvent.inLogs(logs, 'TargetCreated'); - }); - - context('with target', async function () { - beforeEach(async function () { - const { logs } = await this.bounty.createTarget({ from: researcher }); - const event = expectEvent.inLogs(logs, 'TargetCreated'); - this.target = TargetMock.at(event.args.createdAddress); - }); - - context('before exploiting vulnerability', async function () { - it('reverts when claiming reward', async function () { - await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); - }); - }); - - context('after exploiting vulnerability', async function () { - beforeEach(async function () { - await this.target.exploitVulnerability({ from: researcher }); - }); - - it('sends the reward to the researcher', async function () { - await this.bounty.claim(this.target.address, { from: anyone }); - - const researcherPreBalance = await ethGetBalance(researcher); - await this.bounty.withdrawPayments(researcher); - const researcherPostBalance = await ethGetBalance(researcher); - - researcherPostBalance.sub(researcherPreBalance).should.be.bignumber.equal(reward); - (await ethGetBalance(this.bounty.address)).should.be.bignumber.equal(0); - }); - - context('after claiming', async function () { - beforeEach(async function () { - await this.bounty.claim(this.target.address, { from: researcher }); - }); - - it('is not claimable', async function () { - (await this.bounty.claimable()).should.equal(false); - }); - - it('no longer accepts rewards', async function () { - await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); - }); - - it('reverts when reclaimed', async function () { - await assertRevert(this.bounty.claim(this.target.address, { from: researcher })); - }); - }); - }); - }); - - context('with non-target', function () { - it('reverts when claiming reward', async function () { - await assertRevert(this.bounty.claim(nonTarget, { from: researcher })); - }); - }); - }); - - describe('cancelBounty', function () { - context('before canceling', function () { - it('is claimable', async function () { - (await this.bounty.claimable()).should.equal(true); - }); - - it('can be canceled by the owner', async function () { - const { logs } = await this.bounty.cancelBounty({ from: owner }); - expectEvent.inLogs(logs, 'BountyCanceled'); - (await balanceDifference(owner, () => this.bounty.withdrawPayments(owner))) - .should.be.bignumber.equal(reward); - }); - - it('reverts when canceled by anyone', async function () { - await assertRevert(this.bounty.cancelBounty({ from: anyone })); - }); - }); - - context('after canceling', async function () { - beforeEach(async function () { - await this.bounty.cancelBounty({ from: owner }); - }); - - it('is not claimable', async function () { - (await this.bounty.claimable()).should.equal(false); - }); - - it('no longer accepts rewards', async function () { - await assertRevert(ethSendTransaction({ from: owner, to: this.bounty.address, value: reward })); - }); - - it('reverts when recanceled', async function () { - await assertRevert(this.bounty.cancelBounty({ from: owner })); - }); - }); - }); - }); -}); From a9af619c59b05318ca45055d79cc328531e92fe4 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Wed, 26 Sep 2018 22:04:41 +0200 Subject: [PATCH 099/205] Add BigNumber support to expectEvent/inLogs (#1026) (#1338) * Add BigNumber support to expectEvent/inLogs (#1026) * switched direct logs array check to expectEvent method in AllowanceCrowdsale.test.js * Refactor expectEvent.inLogs function to use simple value number check * Introduced should.be.bignumber method to compare BigNumber values * Destructure transaction object to extract logs field (cherry picked from commit 947de54ceea3abe4783ac2e417b6d9bfb93d708e) --- test/crowdsale/AllowanceCrowdsale.test.js | 17 +++++++----- test/helpers/expectEvent.js | 32 ++++++++++++++--------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index f9a7969b9..3e7c638a9 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); @@ -5,7 +6,7 @@ const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -41,12 +42,14 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs( + logs, + 'TokensPurchased', + { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount }); }); it('should assign tokens to sender', async function () { diff --git a/test/helpers/expectEvent.js b/test/helpers/expectEvent.js index 37fa1083e..b857b6636 100644 --- a/test/helpers/expectEvent.js +++ b/test/helpers/expectEvent.js @@ -1,24 +1,18 @@ -const should = require('chai').should(); +const BigNumber = web3.BigNumber; +const should = require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); function inLogs (logs, eventName, eventArgs = {}) { const event = logs.find(function (e) { if (e.event === eventName) { - let matches = true; - for (const [k, v] of Object.entries(eventArgs)) { - if (e.args[k] !== v) { - matches = false; - } - } - - if (matches) { - return true; + contains(e.args, k, v); } + return true; } }); - should.exist(event); - return event; } @@ -27,6 +21,20 @@ async function inTransaction (tx, eventName, eventArgs = {}) { return inLogs(logs, eventName, eventArgs); } +function contains (args, key, value) { + if (isBigNumber(args[key])) { + args[key].should.be.bignumber.equal(value); + } else { + args[key].should.be.equal(value); + } +} + +function isBigNumber (object) { + return object.isBigNumber || + object instanceof BigNumber || + (object.constructor && object.constructor.name === 'BigNumber'); +} + module.exports = { inLogs, inTransaction, From 39db4b4b05ab48731e4d59cadb1e4e4c8bf6c711 Mon Sep 17 00:00:00 2001 From: Jakub Bogacz Date: Thu, 27 Sep 2018 16:33:28 +0200 Subject: [PATCH 100/205] Feature/use expect event in test logs assertions #1232 (#1343) * Add BigNumber support to expectEvent/inLogs (#1026) * switched direct logs array check to expectEvent method in AllowanceCrowdsale.test.js * Refactor expectEvent.inLogs function to use simple value number check * Introduced should.be.bignumber method to compare BigNumber values * Use expectEvent to test logs (#1232) * Removed trailing space (cherry picked from commit 536262f2ec5d6103129283a023b467d8887adce3) --- test/crowdsale/AllowanceCrowdsale.test.js | 14 ++-- test/crowdsale/Crowdsale.test.js | 27 +++---- test/crowdsale/FinalizableCrowdsale.test.js | 6 +- test/crowdsale/MintedCrowdsale.behavior.js | 15 ++-- test/payment/Escrow.behavior.js | 18 ++--- test/payment/RefundEscrow.test.js | 10 ++- test/token/ERC20/ERC20.test.js | 65 +++++++++-------- test/token/ERC20/ERC20Pausable.test.js | 7 +- .../ERC20/behaviors/ERC20Burnable.behavior.js | 18 ++--- .../ERC20/behaviors/ERC20Mintable.behavior.js | 4 +- test/token/ERC721/ERC721.behavior.js | 71 ++++++++++--------- test/token/ERC721/ERC721MintBurn.behavior.js | 14 ++-- 12 files changed, 135 insertions(+), 134 deletions(-) diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 3e7c638a9..e57a8c75a 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -42,14 +42,12 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - expectEvent.inLogs( - logs, - 'TokensPurchased', - { - purchaser: investor, - beneficiary: investor, - value: value, - amount: expectedTokenAmount }); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 89fd53b2d..b7cfefeb0 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../helpers/expectEvent'); const { assertRevert } = require('../helpers/assertRevert'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); @@ -5,7 +6,7 @@ const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -82,12 +83,12 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { @@ -106,12 +107,12 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { describe('low-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: purchaser, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to beneficiary', async function () { diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 187c67a36..b024fe1d4 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); const { increaseTimeTo, duration } = require('../helpers/increaseTime'); const { latestTime } = require('../helpers/latestTime'); @@ -6,7 +7,7 @@ const { EVMRevert } = require('../helpers/EVMRevert'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -50,7 +51,6 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { it('logs finalized', async function () { await increaseTimeTo(this.afterClosingTime); const { logs } = await this.crowdsale.finalize({ from: anyone }); - const event = logs.find(e => e.event === 'CrowdsaleFinalized'); - should.exist(event); + expectEvent.inLogs(logs, 'CrowdsaleFinalized'); }); }); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index f5d61328c..c55850cd9 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -1,8 +1,9 @@ +const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; -const should = require('chai') +require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); @@ -20,12 +21,12 @@ function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate describe('high-level purchase', function () { it('should log purchase', async function () { const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); - const event = logs.find(e => e.event === 'TokensPurchased'); - 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); + expectEvent.inLogs(logs, 'TokensPurchased', { + purchaser: investor, + beneficiary: investor, + value: value, + amount: expectedTokenAmount + }); }); it('should assign tokens to sender', async function () { diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 28abd5af8..2fa197c2f 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -32,10 +32,11 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('emits a deposited event', async function () { - const receipt = await this.escrow.deposit(payee1, { from: primary, value: amount }); - - const event = expectEvent.inLogs(receipt.logs, 'Deposited', { payee: payee1 }); - event.args.weiAmount.should.be.bignumber.equal(amount); + const { logs } = await this.escrow.deposit(payee1, { from: primary, value: amount }); + expectEvent.inLogs(logs, 'Deposited', { + payee: payee1, + weiAmount: amount + }); }); it('can add multiple deposits on a single account', async function () { @@ -84,10 +85,11 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { it('emits a withdrawn event', async function () { await this.escrow.deposit(payee1, { from: primary, value: amount }); - const receipt = await this.escrow.withdraw(payee1, { from: primary }); - - const event = expectEvent.inLogs(receipt.logs, 'Withdrawn', { payee: payee1 }); - event.args.weiAmount.should.be.bignumber.equal(amount); + const { logs } = await this.escrow.withdraw(payee1, { from: primary }); + expectEvent.inLogs(logs, 'Withdrawn', { + payee: payee1, + weiAmount: amount + }); }); }); }); diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index 1bd1a41c2..a3d669d69 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -54,9 +54,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('only the primary account can enter closed state', async function () { await expectThrow(this.escrow.close({ from: beneficiary }), EVMRevert); - const receipt = await this.escrow.close({ from: primary }); - - expectEvent.inLogs(receipt.logs, 'Closed'); + const { logs } = await this.escrow.close({ from: primary }); + expectEvent.inLogs(logs, 'Closed'); }); context('closed state', function () { @@ -94,9 +93,8 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('only the primary account can enter refund state', async function () { await expectThrow(this.escrow.enableRefunds({ from: beneficiary }), EVMRevert); - const receipt = await this.escrow.enableRefunds({ from: primary }); - - expectEvent.inLogs(receipt.logs, 'RefundsEnabled'); + const { logs } = await this.escrow.enableRefunds({ from: primary }); + expectEvent.inLogs(logs, 'RefundsEnabled'); }); context('refund state', function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 5399ae584..eab7c10a5 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -61,12 +61,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits a transfer event', async function () { const { logs } = await this.token.transfer(to, amount, { from: owner }); - const event = expectEvent.inLogs(logs, 'Transfer', { + expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, + value: amount }); - - event.args.value.should.be.bignumber.equal(amount); }); }); }); @@ -90,11 +89,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.approve(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -124,11 +123,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.approve(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -194,11 +193,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits a transfer event', async function () { const { logs } = await this.token.transferFrom(owner, to, amount, { from: spender }); - logs.length.should.equal(1); - logs[0].event.should.equal('Transfer'); - logs[0].args.from.should.equal(owner); - logs[0].args.to.should.equal(to); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: to, + value: amount + }); }); }); @@ -269,11 +268,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.decreaseAllowance(spender, approvedAmount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(0); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: 0 + }); }); it('decreases the spender allowance subtracting the requested amount', async function () { @@ -326,11 +325,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.increaseAllowance(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { @@ -360,11 +359,11 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { it('emits an approval event', async function () { const { logs } = await this.token.increaseAllowance(spender, amount, { from: owner }); - logs.length.should.equal(1); - logs[0].event.should.equal('Approval'); - logs[0].args.owner.should.equal(owner); - logs[0].args.spender.should.equal(spender); - logs[0].args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: amount + }); }); describe('when there was no approved amount before', function () { diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index fa733a3f6..a524e2442 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,3 +1,4 @@ +const expectEvent = require('../../helpers/expectEvent'); const { assertRevert } = require('../../helpers/assertRevert'); const ERC20PausableMock = artifacts.require('ERC20PausableMock'); @@ -30,8 +31,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('emits a Pause event', async function () { const { logs } = await this.token.pause({ from }); - logs.length.should.equal(1); - logs[0].event.should.equal('Paused'); + expectEvent.inLogs(logs, 'Paused'); }); }); @@ -72,8 +72,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('emits an Unpause event', async function () { const { logs } = await this.token.unpause({ from }); - logs.length.should.equal(1); - logs[0].event.should.equal('Unpaused'); + expectEvent.inLogs(logs, 'Unpaused'); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 996beb0e3..299ea26e0 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -29,10 +29,11 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { }); it('emits a transfer event', async function () { - const event = expectEvent.inLogs(this.logs, 'Transfer'); - event.args.from.should.equal(owner); - event.args.to.should.equal(ZERO_ADDRESS); - event.args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(this.logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + value: amount + }); }); } }); @@ -74,10 +75,11 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { }); it('emits a transfer event', async function () { - const event = expectEvent.inLogs(this.logs, 'Transfer'); - event.args.from.should.equal(owner); - event.args.to.should.equal(ZERO_ADDRESS); - event.args.value.should.be.bignumber.equal(amount); + expectEvent.inLogs(this.logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + value: amount + }); }); } }); diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index a5812f655..293a30f3f 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -34,11 +34,11 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { }); it('emits a mint and a transfer event', async function () { - const transferEvent = expectEvent.inLogs(this.logs, 'Transfer', { + expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: anyone, + value: amount }); - transferEvent.args.value.should.be.bignumber.equal(amount); }); } }); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index f521bbb75..c7eab53d4 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,3 +1,4 @@ +const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const { assertRevert } = require('../../helpers/assertRevert'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -88,19 +89,19 @@ function shouldBehaveLikeERC721 ( if (approved) { it('emit only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(this.toWhom); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: this.toWhom, + tokenId: tokenId + }); }); } else { it('emits only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(this.toWhom); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: this.toWhom, + tokenId: tokenId + }); }); } @@ -161,11 +162,11 @@ function shouldBehaveLikeERC721 ( }); it('emits only a transfer event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(owner); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: owner, + tokenId: tokenId + }); }); it('keeps the owner balance', async function () { @@ -337,11 +338,11 @@ function shouldBehaveLikeERC721 ( const itEmitsApprovalEvent = function (address) { it('emits an approval event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Approval'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.approved.should.be.equal(address); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + approved: address, + tokenId: tokenId + }); }); }; @@ -447,11 +448,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); }); @@ -469,11 +470,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); it('can unset the operator approval', async function () { @@ -497,11 +498,11 @@ function shouldBehaveLikeERC721 ( it('emits an approval event', async function () { const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner }); - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('ApprovalForAll'); - logs[0].args.owner.should.be.equal(owner); - logs[0].args.operator.should.be.equal(operator); - logs[0].args.approved.should.equal(true); + expectEvent.inLogs(logs, 'ApprovalForAll', { + owner: owner, + operator: operator, + approved: true + }); }); }); }); diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index e40356561..6afdc2ff5 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -42,11 +42,11 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('emits a transfer and minted event', async function () { - await expectEvent.inLogs(logs, 'Transfer', { + expectEvent.inLogs(logs, 'Transfer', { from: ZERO_ADDRESS, to: newOwner, + tokenId: thirdTokenId }); - logs[0].args.tokenId.should.be.bignumber.equal(thirdTokenId); }); }); @@ -87,11 +87,11 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('emits a burn event', async function () { - logs.length.should.be.equal(1); - logs[0].event.should.be.equal('Transfer'); - logs[0].args.from.should.be.equal(owner); - logs[0].args.to.should.be.equal(ZERO_ADDRESS); - logs[0].args.tokenId.should.be.bignumber.equal(tokenId); + expectEvent.inLogs(logs, 'Transfer', { + from: owner, + to: ZERO_ADDRESS, + tokenId: tokenId + }); }); }); From 598a0358fc900831ec3048f9290478c227cd0ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 28 Sep 2018 22:20:43 -0300 Subject: [PATCH 101/205] Dangling commas are now required. (#1359) (cherry picked from commit a6889776f46adca374b6ebf014aa7b0038112a9d) --- .eslintrc | 2 +- test/crowdsale/AllowanceCrowdsale.test.js | 2 +- test/crowdsale/Crowdsale.test.js | 4 ++-- test/crowdsale/MintedCrowdsale.behavior.js | 2 +- test/payment/Escrow.behavior.js | 4 ++-- test/token/ERC20/ERC20.test.js | 14 +++++++------- .../ERC20/behaviors/ERC20Burnable.behavior.js | 4 ++-- .../ERC20/behaviors/ERC20Mintable.behavior.js | 2 +- test/token/ERC721/ERC721.behavior.js | 14 +++++++------- test/token/ERC721/ERC721MintBurn.behavior.js | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.eslintrc b/.eslintrc index 117135b36..c15a4d515 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,7 @@ // Code style "camelcase": ["error", {"properties": "always"}], - "comma-dangle": ["warn", "always-multiline"], + "comma-dangle": ["error", "always-multiline"], "comma-spacing": ["error", {"before": false, "after": true}], "dot-notation": ["error", {"allowKeywords": true, "allowPattern": ""}], "eol-last": ["error", "always"], diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index e57a8c75a..c6f825126 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -46,7 +46,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index b7cfefeb0..b1f3b381f 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -87,7 +87,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); @@ -111,7 +111,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { purchaser: purchaser, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index c55850cd9..ab8dc8259 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -25,7 +25,7 @@ function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate purchaser: investor, beneficiary: investor, value: value, - amount: expectedTokenAmount + amount: expectedTokenAmount, }); }); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 2fa197c2f..9769291e1 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -35,7 +35,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { const { logs } = await this.escrow.deposit(payee1, { from: primary, value: amount }); expectEvent.inLogs(logs, 'Deposited', { payee: payee1, - weiAmount: amount + weiAmount: amount, }); }); @@ -88,7 +88,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { const { logs } = await this.escrow.withdraw(payee1, { from: primary }); expectEvent.inLogs(logs, 'Withdrawn', { payee: payee1, - weiAmount: amount + weiAmount: amount, }); }); }); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index eab7c10a5..e224de942 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -64,7 +64,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, - value: amount + value: amount, }); }); }); @@ -92,7 +92,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -126,7 +126,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -196,7 +196,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Transfer', { from: owner, to: to, - value: amount + value: amount, }); }); }); @@ -271,7 +271,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: 0 + value: 0, }); }); @@ -328,7 +328,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); @@ -362,7 +362,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { expectEvent.inLogs(logs, 'Approval', { owner: owner, spender: spender, - value: amount + value: amount, }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 299ea26e0..25af3254c 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -32,7 +32,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { expectEvent.inLogs(this.logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount + value: amount, }); }); } @@ -78,7 +78,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { expectEvent.inLogs(this.logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - value: amount + value: amount, }); }); } diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index 293a30f3f..f34504afc 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -37,7 +37,7 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: anyone, - value: amount + value: amount, }); }); } diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index c7eab53d4..a18b6b437 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -92,7 +92,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: this.toWhom, - tokenId: tokenId + tokenId: tokenId, }); }); } else { @@ -100,7 +100,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: this.toWhom, - tokenId: tokenId + tokenId: tokenId, }); }); } @@ -165,7 +165,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: owner, - tokenId: tokenId + tokenId: tokenId, }); }); @@ -341,7 +341,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'Approval', { owner: owner, approved: address, - tokenId: tokenId + tokenId: tokenId, }); }); }; @@ -451,7 +451,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); }); @@ -473,7 +473,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); @@ -501,7 +501,7 @@ function shouldBehaveLikeERC721 ( expectEvent.inLogs(logs, 'ApprovalForAll', { owner: owner, operator: operator, - approved: true + approved: true, }); }); }); diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index 6afdc2ff5..a5141abca 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -45,7 +45,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: ZERO_ADDRESS, to: newOwner, - tokenId: thirdTokenId + tokenId: thirdTokenId, }); }); }); @@ -90,7 +90,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( expectEvent.inLogs(logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, - tokenId: tokenId + tokenId: tokenId, }); }); }); From c25a1e366f2c27231d938d9d91507cac5c57e0ef Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 1 Oct 2018 18:09:57 +0530 Subject: [PATCH 102/205] Fix #1358 Test helper to send funds (#1367) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * fixes #1358 * linting done * suggested changes (cherry picked from commit fa1dfbd113dee461ab9860514c9ad487fabfcfee) --- test/helpers/sendTransaction.js | 9 +++++++++ test/payment/SplitPayment.test.js | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/test/helpers/sendTransaction.js b/test/helpers/sendTransaction.js index e49376b44..9d4f3068f 100644 --- a/test/helpers/sendTransaction.js +++ b/test/helpers/sendTransaction.js @@ -15,7 +15,16 @@ function sendTransaction (target, name, argsTypes, argsValues, opts) { return target.sendTransaction(Object.assign({ data: encodedData }, opts)); } +function sendEther (from, to, value) { + web3.eth.sendTransaction({ + from: from, + to: to, + value: value, + gasPrice: 0, + }); +} module.exports = { findMethod, sendTransaction, + sendEther, }; diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index c1ed22ead..c4a720fb9 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -1,4 +1,5 @@ -const { ethGetBalance, ethSendTransaction } = require('../helpers/web3'); +const { ethGetBalance } = require('../helpers/web3'); +const { sendEther } = require('./../helpers/sendTransaction'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('./../helpers/constants'); @@ -59,7 +60,7 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should accept payments', async function () { - await ethSendTransaction({ from: owner, to: this.contract.address, value: amount }); + await sendEther(owner, this.contract.address, amount); (await ethGetBalance(this.contract.address)).should.be.bignumber.equal(amount); }); @@ -77,12 +78,12 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should throw if non-payee want to claim', async function () { - await ethSendTransaction({ from: payer1, to: this.contract.address, value: amount }); + await sendEther(payer1, this.contract.address, amount); await expectThrow(this.contract.release(nonpayee1), EVMRevert); }); it('should distribute funds to payees', async function () { - await ethSendTransaction({ from: payer1, to: this.contract.address, value: amount }); + await sendEther(payer1, this.contract.address, amount); // receive funds const initBalance = await ethGetBalance(this.contract.address); From b03932529ce4ba1ef2caf4520700d452da99853b Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Mon, 1 Oct 2018 20:53:47 +0530 Subject: [PATCH 103/205] Fix/#1355 test helper to check balance difference (#1368) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * fixex #1355 * linting * suggested changes * Update BreakInvariantBounty.test.js (cherry picked from commit 6ae041bca61ff2d6c25acc865b0152cf54122528) --- test/helpers/balanceDiff.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/helpers/balanceDiff.js diff --git a/test/helpers/balanceDiff.js b/test/helpers/balanceDiff.js new file mode 100644 index 000000000..8f88ba400 --- /dev/null +++ b/test/helpers/balanceDiff.js @@ -0,0 +1,10 @@ +async function balanceDifference (account, promise) { + const balanceBefore = web3.eth.getBalance(account); + await promise(); + const balanceAfter = web3.eth.getBalance(account); + return balanceAfter.minus(balanceBefore); +} + +module.exports = { + balanceDifference, +}; From 0678f67289e0e97600c0142427c5d44818b67223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 07:07:11 -0300 Subject: [PATCH 104/205] Merged latestTime, increaseTime and duration into a time helper. (#1364) (cherry picked from commit 34bc709bc2e5117cdd762e92a29ed88557532e61) --- test/crowdsale/FinalizableCrowdsale.test.js | 15 ++++++------ .../IncreasingPriceCrowdsale.test.js | 23 +++++++++--------- test/crowdsale/PostDeliveryCrowdsale.test.js | 13 +++++----- test/crowdsale/RefundableCrowdsale.test.js | 15 ++++++------ test/crowdsale/TimedCrowdsale.test.js | 19 +++++++-------- test/examples/SampleCrowdsale.test.js | 23 +++++++++--------- test/helpers/latestTime.js | 11 --------- test/helpers/{increaseTime.js => time.js} | 21 ++++++++++------ test/token/ERC20/TokenTimelock.test.js | 15 ++++++------ test/token/ERC20/TokenVesting.test.js | 24 +++++++++---------- 10 files changed, 84 insertions(+), 95 deletions(-) delete mode 100644 test/helpers/latestTime.js rename test/helpers/{increaseTime.js => time.js} (78%) diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index b024fe1d4..6eea7f2f2 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,7 +1,6 @@ const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); @@ -23,9 +22,9 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await ERC20.new(); this.crowdsale = await FinalizableCrowdsaleImpl.new( @@ -38,18 +37,18 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); it('can be finalized by anyone after ending', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); it('cannot be finalized twice', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); }); it('logs finalized', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); const { logs } = await this.crowdsale.finalize({ from: anyone }); expectEvent.inLogs(logs, 'CrowdsaleFinalized'); }); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 767b5f8e5..2024d7751 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { assertRevert } = require('../helpers/assertRevert'); const BigNumber = web3.BigNumber; @@ -29,9 +28,9 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) beforeEach(async function () { await advanceBlock(); - this.startTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.startTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.startTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.startTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); }); @@ -61,43 +60,43 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('at start', async function () { - await increaseTimeTo(this.startTime); + await time.increaseTo(this.startTime); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(initialRate)); }); it('at time 150', async function () { - await increaseTimeTo(this.startTime + 150); + await time.increaseTo(this.startTime + 150); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime150)); }); it('at time 300', async function () { - await increaseTimeTo(this.startTime + 300); + await time.increaseTo(this.startTime + 300); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime300)); }); it('at time 1500', async function () { - await increaseTimeTo(this.startTime + 1500); + await time.increaseTo(this.startTime + 1500); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime1500)); }); it('at time 30', async function () { - await increaseTimeTo(this.startTime + 30); + await time.increaseTo(this.startTime + 30); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime30)); }); it('at time 150000', async function () { - await increaseTimeTo(this.startTime + 150000); + await time.increaseTo(this.startTime + 150000); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime150000)); }); it('at time 450000', async function () { - await increaseTimeTo(this.startTime + 450000); + await time.increaseTo(this.startTime + 450000); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(value.mul(rateAtTime450000)); }); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 94ebd808b..866e4da15 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -1,6 +1,5 @@ const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ether } = require('../helpers/ether'); @@ -24,9 +23,9 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); this.crowdsale = await PostDeliveryCrowdsaleImpl.new( this.openingTime, this.closingTime, rate, wallet, this.token.address @@ -36,7 +35,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { context('after opening time', function () { beforeEach(async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); }); context('with bought tokens', function () { @@ -57,7 +56,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { context('after closing time', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); }); it('allows beneficiaries to withdraw tokens', async function () { diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 749ec5cac..77e0bfebb 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); @@ -27,9 +26,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.preWalletBalance = await ethGetBalance(wallet); this.token = await SimpleToken.new(); @@ -61,7 +60,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after opening time', function () { beforeEach(async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); }); it('denies refunds', async function () { @@ -75,7 +74,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after closing time and finalization', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); @@ -95,7 +94,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('after closing time and finalization', function () { beforeEach(async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); }); diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index df3e01c81..cfbc3d3cf 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); @@ -25,21 +24,21 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SimpleToken.new(); }); it('rejects an opening time in the past', async function () { await expectThrow(TimedCrowdsaleImpl.new( - (await latestTime()) - duration.days(1), this.closingTime, rate, wallet, this.token.address + (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address ), EVMRevert); }); it('rejects a closing time before the opening time', async function () { await expectThrow(TimedCrowdsaleImpl.new( - this.openingTime, this.openingTime - duration.seconds(1), rate, wallet, this.token.address + this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address ), EVMRevert); }); @@ -53,7 +52,7 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { it('should be ended only after end', async function () { (await this.crowdsale.hasClosed()).should.equal(false); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); (await this.crowdsale.isOpen()).should.equal(false); (await this.crowdsale.hasClosed()).should.equal(true); }); @@ -66,14 +65,14 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('should accept payments after start', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); (await this.crowdsale.isOpen()).should.equal(true); await this.crowdsale.send(value); await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); }); it('should reject payments after end', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await expectThrow(this.crowdsale.send(value), EVMRevert); await expectThrow(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }), EVMRevert); }); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index e47143535..303ddf704 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -1,7 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); -const { increaseTimeTo, duration } = require('../helpers/increaseTime'); -const { latestTime } = require('../helpers/latestTime'); +const time = require('../helpers/time'); const { expectThrow } = require('../helpers/expectThrow'); const { EVMRevert } = require('../helpers/EVMRevert'); const { assertRevert } = require('../helpers/assertRevert'); @@ -27,9 +26,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); beforeEach(async function () { - this.openingTime = (await latestTime()) + duration.weeks(1); - this.closingTime = this.openingTime + duration.weeks(1); - this.afterClosingTime = this.closingTime + duration.seconds(1); + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); this.token = await SampleCrowdsaleToken.new({ from: deployer }); this.crowdsale = await SampleCrowdsale.new( @@ -68,7 +67,7 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { const investmentAmount = ether(1); const expectedTokenAmount = RATE.mul(investmentAmount); - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.buyTokens(investor, { value: investmentAmount, from: investor }); (await this.token.balanceOf(investor)).should.be.bignumber.equal(expectedTokenAmount); @@ -76,23 +75,23 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); it('should reject payments after end', async function () { - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await expectThrow(this.crowdsale.send(ether(1)), EVMRevert); await expectThrow(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor }), EVMRevert); }); it('should reject payments over cap', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.send(CAP); await expectThrow(this.crowdsale.send(1), EVMRevert); }); it('should allow finalization and transfer funds to wallet if the goal is reached', async function () { - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.send(GOAL); const beforeFinalization = await ethGetBalance(wallet); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: owner }); const afterFinalization = await ethGetBalance(wallet); @@ -102,9 +101,9 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { it('should allow refunds if the goal is not reached', async function () { const balanceBeforeInvestment = await ethGetBalance(investor); - await increaseTimeTo(this.openingTime); + await time.increaseTo(this.openingTime); await this.crowdsale.sendTransaction({ value: ether(1), from: investor, gasPrice: 0 }); - await increaseTimeTo(this.afterClosingTime); + await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: owner }); await this.crowdsale.claimRefund(investor, { gasPrice: 0 }); diff --git a/test/helpers/latestTime.js b/test/helpers/latestTime.js deleted file mode 100644 index fee9521d6..000000000 --- a/test/helpers/latestTime.js +++ /dev/null @@ -1,11 +0,0 @@ -const { ethGetBlock } = require('./web3'); - -// Returns the time of the last mined block in seconds -async function latestTime () { - const block = await ethGetBlock('latest'); - return block.timestamp; -} - -module.exports = { - latestTime, -}; diff --git a/test/helpers/increaseTime.js b/test/helpers/time.js similarity index 78% rename from test/helpers/increaseTime.js rename to test/helpers/time.js index b22ba6b04..b7f3c0001 100644 --- a/test/helpers/increaseTime.js +++ b/test/helpers/time.js @@ -1,7 +1,13 @@ -const { latestTime } = require('./latestTime'); +const { ethGetBlock } = require('./web3'); + +// Returns the time of the last mined block in seconds +async function latest () { + const block = await ethGetBlock('latest'); + return block.timestamp; +} // Increases ganache time by the passed duration in seconds -function increaseTime (duration) { +function increase (duration) { const id = Date.now(); return new Promise((resolve, reject) => { @@ -31,12 +37,12 @@ function increaseTime (duration) { * * @param target time in seconds */ -async function increaseTimeTo (target) { - const now = (await latestTime()); +async function increaseTo (target) { + const now = (await latest()); if (target < now) throw Error(`Cannot increase current time(${now}) to a moment in the past(${target})`); const diff = target - now; - return increaseTime(diff); + return increase(diff); } const duration = { @@ -49,7 +55,8 @@ const duration = { }; module.exports = { - increaseTime, - increaseTimeTo, + latest, + increase, + increaseTo, duration, }; diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index c10b1b821..04441fd1e 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -1,5 +1,4 @@ -const { latestTime } = require('../../helpers/latestTime'); -const { increaseTimeTo, duration } = require('../../helpers/increaseTime'); +const time = require('../../helpers/time'); const { expectThrow } = require('../../helpers/expectThrow'); const BigNumber = web3.BigNumber; @@ -20,7 +19,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('rejects a release time in the past', async function () { - const pastReleaseTime = (await latestTime()) - duration.years(1); + const pastReleaseTime = (await time.latest()) - time.duration.years(1); await expectThrow( TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime) ); @@ -28,7 +27,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { context('once deployed', function () { beforeEach(async function () { - this.releaseTime = (await latestTime()) + duration.years(1); + this.releaseTime = (await time.latest()) + time.duration.years(1); this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime); await this.token.mint(this.timelock.address, amount, { from: minter }); }); @@ -44,24 +43,24 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('cannot be released just before time limit', async function () { - await increaseTimeTo(this.releaseTime - duration.seconds(3)); + await time.increaseTo(this.releaseTime - time.duration.seconds(3)); await expectThrow(this.timelock.release()); }); it('can be released just after limit', async function () { - await increaseTimeTo(this.releaseTime + duration.seconds(1)); + await time.increaseTo(this.releaseTime + time.duration.seconds(1)); await this.timelock.release(); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); it('can be released after time limit', async function () { - await increaseTimeTo(this.releaseTime + duration.years(1)); + await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); it('cannot be released twice', async function () { - await increaseTimeTo(this.releaseTime + duration.years(1)); + await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); await expectThrow(this.timelock.release()); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index b88f8a673..acfdb9adc 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -1,7 +1,6 @@ const { expectThrow } = require('../../helpers/expectThrow'); const { EVMRevert } = require('../../helpers/EVMRevert'); -const { latestTime } = require('../../helpers/latestTime'); -const { increaseTimeTo, duration } = require('../../helpers/increaseTime'); +const time = require('../../helpers/time'); const { ethGetBlock } = require('../../helpers/web3'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -18,9 +17,10 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { const amount = new BigNumber(1000); beforeEach(async function () { - this.start = (await latestTime()) + duration.minutes(1); // +1 minute so it starts after contract instantiation - this.cliffDuration = duration.years(1); - this.duration = duration.years(2); + // +1 minute so it starts after contract instantiation + this.start = (await time.latest()) + time.duration.minutes(1); + this.cliffDuration = time.duration.years(1); + this.duration = time.duration.years(2); }); it('rejects a duration shorter than the cliff', async function () { @@ -65,12 +65,12 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('can be released after cliff', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(1)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(1)); await this.vesting.release(this.token.address); }); it('should release proper amount after cliff', async function () { - await increaseTimeTo(this.start + this.cliffDuration); + await time.increaseTo(this.start + this.cliffDuration); const { receipt } = await this.vesting.release(this.token.address); const block = await ethGetBlock(receipt.blockNumber); @@ -87,7 +87,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { for (let i = 1; i <= checkpoints; i++) { const now = this.start + this.cliffDuration + i * (vestingPeriod / checkpoints); - await increaseTimeTo(now); + await time.increaseTo(now); await this.vesting.release(this.token.address); const expectedVesting = amount.mul(now - this.start).div(this.duration).floor(); @@ -97,7 +97,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should have released all after end', async function () { - await increaseTimeTo(this.start + this.duration); + await time.increaseTo(this.start + this.duration); await this.vesting.release(this.token.address); (await this.token.balanceOf(beneficiary)).should.bignumber.equal(amount); (await this.vesting.released(this.token.address)).should.bignumber.equal(amount); @@ -120,7 +120,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should return the non-vested tokens when revoked by owner', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); const vested = await this.vesting.vestedAmount(this.token.address); @@ -130,7 +130,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should keep the vested tokens when revoked by owner', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); const vestedPre = await this.vesting.vestedAmount(this.token.address); @@ -142,7 +142,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should fail to be revoked a second time', async function () { - await increaseTimeTo(this.start + this.cliffDuration + duration.weeks(12)); + await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); await this.vesting.vestedAmount(this.token.address); From 2f3f0d3c8a5840b62aa2f1083654f1fdbe7fb08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 10:37:44 -0300 Subject: [PATCH 105/205] Created test utils directory (cherry picked from commit 269981ee6a02096a20f6997d87e8d43b78906284) --- test/{ => utils}/Address.test.js | 0 test/{ => utils}/ReentrancyGuard.test.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/{ => utils}/Address.test.js (100%) rename test/{ => utils}/ReentrancyGuard.test.js (100%) diff --git a/test/Address.test.js b/test/utils/Address.test.js similarity index 100% rename from test/Address.test.js rename to test/utils/Address.test.js diff --git a/test/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js similarity index 100% rename from test/ReentrancyGuard.test.js rename to test/utils/ReentrancyGuard.test.js From 13fb1f662a67cb2d63a2a786055a45fcb285163c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 2 Oct 2018 10:48:54 -0300 Subject: [PATCH 106/205] Fixed test path. (cherry picked from commit f4d6f404424669e0eef7faa05fd89ab9945f265b) --- test/utils/ReentrancyGuard.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 7086f8d94..27430652c 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('./helpers/expectThrow'); +const { expectThrow } = require('../helpers/expectThrow'); const ReentrancyMock = artifacts.require('ReentrancyMock'); const ReentrancyAttack = artifacts.require('ReentrancyAttack'); From 109eba9273f37a70ddbfc32f64d11a91078e47b8 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 4 Oct 2018 16:21:52 +0530 Subject: [PATCH 107/205] Replaces `amount` with `value` for consistency (#1378) * fixes #1372 * done in ERC20Capped and ERC20Mintable (cherry picked from commit fd4de776519e2bd64dc6ac0efb87e0f603c6608f) --- contracts/token/ERC20/ERC20.sol | 32 ++++++++++++------------- contracts/token/ERC20/ERC20Capped.sol | 8 +++---- contracts/token/ERC20/ERC20Mintable.sol | 6 ++--- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 3d18c1dec..25b2694a2 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -168,28 +168,28 @@ contract ERC20 is IERC20 { * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. - * @param amount The amount that will be created. + * @param value The amount that will be created. */ - function _mint(address account, uint256 amount) internal { + function _mint(address account, uint256 value) internal { require(account != 0); - _totalSupply = _totalSupply.add(amount); - _balances[account] = _balances[account].add(amount); - emit Transfer(address(0), account, amount); + _totalSupply = _totalSupply.add(value); + _balances[account] = _balances[account].add(value); + emit Transfer(address(0), account, value); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. - * @param amount The amount that will be burnt. + * @param value The amount that will be burnt. */ - function _burn(address account, uint256 amount) internal { + function _burn(address account, uint256 value) internal { require(account != 0); - require(amount <= _balances[account]); + require(value <= _balances[account]); - _totalSupply = _totalSupply.sub(amount); - _balances[account] = _balances[account].sub(amount); - emit Transfer(account, address(0), amount); + _totalSupply = _totalSupply.sub(value); + _balances[account] = _balances[account].sub(value); + emit Transfer(account, address(0), value); } /** @@ -197,15 +197,15 @@ contract ERC20 is IERC20 { * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * @param account The account whose tokens will be burnt. - * @param amount The amount that will be burnt. + * @param value The amount that will be burnt. */ - function _burnFrom(address account, uint256 amount) internal { - require(amount <= _allowed[account][msg.sender]); + function _burnFrom(address account, uint256 value) internal { + require(value <= _allowed[account][msg.sender]); // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, // this function needs to emit an event with the updated approval. _allowed[account][msg.sender] = _allowed[account][msg.sender].sub( - amount); - _burn(account, amount); + value); + _burn(account, value); } } diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 0a73159b6..9f3ea8bfc 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -27,19 +27,19 @@ contract ERC20Capped is ERC20Mintable { /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. - * @param amount The amount of tokens to mint. + * @param value The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address to, - uint256 amount + uint256 value ) public returns (bool) { - require(totalSupply().add(amount) <= _cap); + require(totalSupply().add(value) <= _cap); - return super.mint(to, amount); + return super.mint(to, value); } } diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index 386abf64d..eb01f06e7 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -11,18 +11,18 @@ contract ERC20Mintable is ERC20, MinterRole { /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. - * @param amount The amount of tokens to mint. + * @param value The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address to, - uint256 amount + uint256 value ) public onlyMinter returns (bool) { - _mint(to, amount); + _mint(to, value); return true; } } From eae40c93b63995f1c1ebe3f16340177485003309 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 4 Oct 2018 18:27:37 +0530 Subject: [PATCH 108/205] `this` is used in tests (#1380) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1200 * suggested change (cherry picked from commit b41b125c15c9ccf8a002a43ed64b5349982c2fb6) --- test/examples/SimpleToken.test.js | 18 ++++++++---------- test/library/MerkleProof.test.js | 10 ++++------ test/token/ERC20/ERC20Detailed.test.js | 10 ++++------ test/utils/ReentrancyGuard.test.js | 13 +++++-------- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index 49b8a7aa4..e7f8fa5c1 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -9,32 +9,30 @@ require('chai') .should(); contract('SimpleToken', function ([_, creator]) { - let token; - beforeEach(async function () { - token = await SimpleToken.new({ from: creator }); + this.token = await SimpleToken.new({ from: creator }); }); it('has a name', async function () { - (await token.name()).should.equal('SimpleToken'); + (await this.token.name()).should.equal('SimpleToken'); }); it('has a symbol', async function () { - (await token.symbol()).should.equal('SIM'); + (await this.token.symbol()).should.equal('SIM'); }); it('has 18 decimals', async function () { - (await token.decimals()).should.be.bignumber.equal(18); + (await this.token.decimals()).should.be.bignumber.equal(18); }); it('assigns the initial total supply to the creator', async function () { - const totalSupply = await token.totalSupply(); - const creatorBalance = await token.balanceOf(creator); + const totalSupply = await this.token.totalSupply(); + const creatorBalance = await this.token.balanceOf(creator); creatorBalance.should.be.bignumber.equal(totalSupply); - const receipt = await web3.eth.getTransactionReceipt(token.transactionHash); - const logs = decodeLogs(receipt.logs, SimpleToken, token.address); + const receipt = await web3.eth.getTransactionReceipt(this.token.transactionHash); + const logs = decodeLogs(receipt.logs, SimpleToken, this.token.address); logs.length.should.equal(1); logs[0].event.should.equal('Transfer'); logs[0].args.from.valueOf().should.equal(ZERO_ADDRESS); diff --git a/test/library/MerkleProof.test.js b/test/library/MerkleProof.test.js index 6674880b7..b5d8fbe07 100644 --- a/test/library/MerkleProof.test.js +++ b/test/library/MerkleProof.test.js @@ -7,10 +7,8 @@ require('chai') .should(); contract('MerkleProof', function () { - let merkleProof; - beforeEach(async function () { - merkleProof = await MerkleProofWrapper.new(); + this.merkleProof = await MerkleProofWrapper.new(); }); describe('verify', function () { @@ -24,7 +22,7 @@ contract('MerkleProof', function () { const leaf = bufferToHex(sha3(elements[0])); - (await merkleProof.verify(proof, root, leaf)).should.equal(true); + (await this.merkleProof.verify(proof, root, leaf)).should.equal(true); }); it('should return false for an invalid Merkle proof', async function () { @@ -40,7 +38,7 @@ contract('MerkleProof', function () { const badProof = badMerkleTree.getHexProof(badElements[0]); - (await merkleProof.verify(badProof, correctRoot, correctLeaf)).should.equal(false); + (await this.merkleProof.verify(badProof, correctRoot, correctLeaf)).should.equal(false); }); it('should return false for a Merkle proof of invalid length', async function () { @@ -54,7 +52,7 @@ contract('MerkleProof', function () { const leaf = bufferToHex(sha3(elements[0])); - (await merkleProof.verify(badProof, root, leaf)).should.equal(false); + (await this.merkleProof.verify(badProof, root, leaf)).should.equal(false); }); }); }); diff --git a/test/token/ERC20/ERC20Detailed.test.js b/test/token/ERC20/ERC20Detailed.test.js index 71b22a7b9..7965b7e9d 100644 --- a/test/token/ERC20/ERC20Detailed.test.js +++ b/test/token/ERC20/ERC20Detailed.test.js @@ -7,25 +7,23 @@ require('chai') const ERC20DetailedMock = artifacts.require('ERC20DetailedMock'); contract('ERC20Detailed', function () { - let detailedERC20 = null; - const _name = 'My Detailed ERC20'; const _symbol = 'MDT'; const _decimals = 18; beforeEach(async function () { - detailedERC20 = await ERC20DetailedMock.new(_name, _symbol, _decimals); + this.detailedERC20 = await ERC20DetailedMock.new(_name, _symbol, _decimals); }); it('has a name', async function () { - (await detailedERC20.name()).should.be.equal(_name); + (await this.detailedERC20.name()).should.be.equal(_name); }); it('has a symbol', async function () { - (await detailedERC20.symbol()).should.be.equal(_symbol); + (await this.detailedERC20.symbol()).should.be.equal(_symbol); }); it('has an amount of decimals', async function () { - (await detailedERC20.decimals()).should.be.bignumber.equal(_decimals); + (await this.detailedERC20.decimals()).should.be.bignumber.equal(_decimals); }); }); diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 27430652c..3952b2fcb 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -9,17 +9,14 @@ require('chai') .should(); contract('ReentrancyGuard', function () { - let reentrancyMock; - beforeEach(async function () { - reentrancyMock = await ReentrancyMock.new(); - const initialCounter = await reentrancyMock.counter(); - initialCounter.should.be.bignumber.equal(0); + this.reentrancyMock = await ReentrancyMock.new(); + (await this.reentrancyMock.counter()).should.be.bignumber.equal(0); }); it('should not allow remote callback', async function () { const attacker = await ReentrancyAttack.new(); - await expectThrow(reentrancyMock.countAndCall(attacker.address)); + await expectThrow(this.reentrancyMock.countAndCall(attacker.address)); }); // The following are more side-effects than intended behavior: @@ -27,10 +24,10 @@ contract('ReentrancyGuard', function () { // in the side-effects. it('should not allow local recursion', async function () { - await expectThrow(reentrancyMock.countLocalRecursive(10)); + await expectThrow(this.reentrancyMock.countLocalRecursive(10)); }); it('should not allow indirect local recursion', async function () { - await expectThrow(reentrancyMock.countThisRecursive(10)); + await expectThrow(this.reentrancyMock.countThisRecursive(10)); }); }); From 620d524398df5260d7cd9e5f90a8f4dc64ce5362 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Tue, 9 Oct 2018 22:02:45 +0530 Subject: [PATCH 109/205] Improves Ownable events (#1397) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1392 * event tests added * constructor event added (cherry picked from commit af42c39e6cb835b220c2ce8ef6247f074707baf7) From 7cd0d5a452e313704c56507921673f9a8fc91a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 9 Oct 2018 16:23:55 -0300 Subject: [PATCH 110/205] Replaced assertJump, assertRevert and expectThrow with shouldFail. (#1363) * Replaced assertJump, assertRevert and expectThrow with shouldFail. * Fixed linter errors. * Fixed typo. * Made the helpers async. (cherry picked from commit b0da0fded0adcaf1f5ae9c4d62d39ac05763afea) --- test/access/Roles.test.js | 9 +++-- test/access/roles/PublicRole.behavior.js | 10 ++--- test/crowdsale/AllowanceCrowdsale.test.js | 4 +- test/crowdsale/CappedCrowdsale.test.js | 18 ++------- test/crowdsale/Crowdsale.test.js | 14 +++---- test/crowdsale/FinalizableCrowdsale.test.js | 7 ++-- .../IncreasingPriceCrowdsale.test.js | 6 +-- .../IndividuallyCappedCrowdsale.test.js | 15 ++++---- test/crowdsale/MintedCrowdsale.test.js | 6 +-- test/crowdsale/PostDeliveryCrowdsale.test.js | 7 ++-- test/crowdsale/RefundableCrowdsale.test.js | 16 +++----- test/crowdsale/TimedCrowdsale.test.js | 19 +++++----- test/drafts/ERC20Migrator.test.js | 13 ++++--- test/drafts/SignatureBouncer.test.js | 26 ++++++------- test/examples/SampleCrowdsale.test.js | 22 ++++------- test/helpers/EVMRevert.js | 5 --- test/helpers/EVMThrow.js | 5 --- test/helpers/assertJump.js | 15 -------- test/helpers/assertRevert.js | 16 -------- test/helpers/expectThrow.js | 28 -------------- test/helpers/shouldFail.js | 31 +++++++++++++++ test/introspection/ERC165.test.js | 4 +- test/library/ECDSA.test.js | 4 +- test/lifecycle/Pausable.test.js | 16 ++++---- test/math/SafeMath.test.js | 12 +++--- test/ownership/Ownable.behavior.js | 9 ++--- test/ownership/Secondary.test.js | 11 +++--- test/payment/ConditionalEscrow.test.js | 6 +-- test/payment/Escrow.behavior.js | 7 ++-- test/payment/RefundEscrow.test.js | 29 +++++++------- test/payment/SplitPayment.test.js | 19 +++++----- test/token/ERC20/ERC20.test.js | 36 +++++++++--------- test/token/ERC20/ERC20Capped.test.js | 4 +- test/token/ERC20/ERC20Pausable.test.js | 20 +++++----- test/token/ERC20/SafeERC20.test.js | 9 ++--- test/token/ERC20/TokenTimelock.test.js | 10 ++--- test/token/ERC20/TokenVesting.test.js | 22 +++-------- .../ERC20/behaviors/ERC20Burnable.behavior.js | 8 ++-- .../ERC20/behaviors/ERC20Capped.behavior.js | 6 +-- .../ERC20/behaviors/ERC20Mintable.behavior.js | 4 +- test/token/ERC721/ERC721.behavior.js | 38 +++++++++++-------- test/token/ERC721/ERC721Full.test.js | 20 +++++----- test/token/ERC721/ERC721MintBurn.behavior.js | 12 +++--- .../ERC721/ERC721PausedToken.behavior.js | 12 +++--- test/utils/ReentrancyGuard.test.js | 8 ++-- 45 files changed, 274 insertions(+), 344 deletions(-) delete mode 100644 test/helpers/EVMRevert.js delete mode 100644 test/helpers/EVMThrow.js delete mode 100644 test/helpers/assertJump.js delete mode 100644 test/helpers/assertRevert.js delete mode 100644 test/helpers/expectThrow.js create mode 100644 test/helpers/shouldFail.js diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 76517492c..869217776 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const RolesMock = artifacts.require('RolesMock'); require('chai') @@ -11,7 +12,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when querying roles for the null account', async function () { - await assertRevert(this.roles.has(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.has(ZERO_ADDRESS)); }); context('initially', function () { @@ -35,7 +36,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when adding roles to the null account', async function () { - await assertRevert(this.roles.add(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.add(ZERO_ADDRESS)); }); }); }); @@ -58,7 +59,7 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { }); it('reverts when removing roles from the null account', async function () { - await assertRevert(this.roles.remove(ZERO_ADDRESS)); + await shouldFail.reverting(this.roles.remove(ZERO_ADDRESS)); }); }); }); diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index a3067f88e..57b94cf97 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const expectEvent = require('../../helpers/expectEvent'); @@ -20,7 +20,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when querying roles for the null account', async function () { - await assertRevert(this.contract[`is${rolename}`](ZERO_ADDRESS)); + await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS)); }); describe('access control', function () { @@ -36,7 +36,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role const from = anyone; it('reverts', async function () { - await assertRevert(this.contract[`only${rolename}Mock`]({ from })); + await shouldFail.reverting(this.contract[`only${rolename}Mock`]({ from })); }); }); }); @@ -58,7 +58,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when adding role to the null account', async function () { - await assertRevert(this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized })); + await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized })); }); }); @@ -79,7 +79,7 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); it('reverts when removing role from the null account', async function () { - await assertRevert(this.contract[`remove${rolename}`](ZERO_ADDRESS)); + await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS)); }); }); diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index c6f825126..4298dcce6 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,6 +1,6 @@ const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ethGetBalance } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -74,7 +74,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW describe('when token wallet is different from token address', function () { it('creation reverts', async function () { this.token = await SimpleToken.new({ from: tokenWallet }); - await assertRevert(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); + await shouldFail.reverting(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS)); }); }); }); diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index 5ccfafba3..a073d7a4e 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -1,6 +1,5 @@ const { ether } = require('../helpers/ether'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -22,10 +21,7 @@ contract('CappedCrowdsale', function ([_, wallet]) { }); it('rejects a cap of zero', async function () { - await expectThrow( - CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0), - EVMRevert, - ); + await shouldFail.reverting(CappedCrowdsaleImpl.new(rate, wallet, this.token.address, 0)); }); context('with crowdsale', function () { @@ -42,17 +38,11 @@ contract('CappedCrowdsale', function ([_, wallet]) { it('should reject payments outside cap', async function () { await this.crowdsale.send(cap); - await expectThrow( - this.crowdsale.send(1), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(1)); }); it('should reject payments that exceed cap', async function () { - await expectThrow( - this.crowdsale.send(cap.plus(1)), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(cap.plus(1))); }); }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index b1f3b381f..8875e9157 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,5 +1,5 @@ const expectEvent = require('../helpers/expectEvent'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const { ethGetBalance } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -20,7 +20,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { const expectedTokenAmount = rate.mul(value); it('requires a non-null token', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(rate, wallet, ZERO_ADDRESS) ); }); @@ -31,13 +31,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('requires a non-zero rate', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(0, wallet, this.token.address) ); }); it('requires a non-null wallet', async function () { - await assertRevert( + await shouldFail.reverting( Crowdsale.new(rate, ZERO_ADDRESS, this.token.address) ); }); @@ -55,7 +55,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('reverts on zero-valued payments', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.send(0, { from: purchaser }) ); }); @@ -67,13 +67,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('reverts on zero-valued payments', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.buyTokens(investor, { value: 0, from: purchaser }) ); }); it('requires a non-null beneficiary', async function () { - await assertRevert( + await shouldFail.reverting( this.crowdsale.buyTokens(ZERO_ADDRESS, { value: value, from: purchaser }) ); }); diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 6eea7f2f2..93d406432 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,8 +1,7 @@ const expectEvent = require('../helpers/expectEvent'); const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -33,7 +32,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { }); it('cannot be finalized before ending', async function () { - await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.finalize({ from: anyone })); }); it('can be finalized by anyone after ending', async function () { @@ -44,7 +43,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { it('cannot be finalized twice', async function () { await time.increaseTo(this.afterClosingTime); await this.crowdsale.finalize({ from: anyone }); - await expectThrow(this.crowdsale.finalize({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.finalize({ from: anyone })); }); it('logs finalized', async function () { diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 2024d7751..a76186bbc 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -1,7 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -35,13 +35,13 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) }); it('rejects a final rate larger than the initial rate', async function () { - await assertRevert(IncreasingPriceCrowdsaleImpl.new( + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); it('rejects a final rate of zero', async function () { - await assertRevert(IncreasingPriceCrowdsaleImpl.new( + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); }); diff --git a/test/crowdsale/IndividuallyCappedCrowdsale.test.js b/test/crowdsale/IndividuallyCappedCrowdsale.test.js index 70c01a6b9..c92fad466 100644 --- a/test/crowdsale/IndividuallyCappedCrowdsale.test.js +++ b/test/crowdsale/IndividuallyCappedCrowdsale.test.js @@ -1,6 +1,5 @@ const { ether } = require('../helpers/ether'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -42,7 +41,7 @@ contract('IndividuallyCappedCrowdsale', function ( }); it('reverts when a non-capper sets a cap', async function () { - await expectThrow(this.crowdsale.setCap(alice, capAlice, { from: anyone }), EVMRevert); + await shouldFail.reverting(this.crowdsale.setCap(alice, capAlice, { from: anyone })); }); context('with individual caps', function () { @@ -60,21 +59,21 @@ contract('IndividuallyCappedCrowdsale', function ( it('should reject payments outside cap', async function () { await this.crowdsale.buyTokens(alice, { value: capAlice }); - await expectThrow(this.crowdsale.buyTokens(alice, { value: 1 }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: 1 })); }); it('should reject payments that exceed cap', async function () { - await expectThrow(this.crowdsale.buyTokens(alice, { value: capAlice.plus(1) }), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(bob, { value: capBob.plus(1) }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(alice, { value: capAlice.plus(1) })); + await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: capBob.plus(1) })); }); it('should manage independent caps', async function () { await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice }); - await expectThrow(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(bob, { value: lessThanCapAlice })); }); it('should default to a cap of zero', async function () { - await expectThrow(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth }), EVMRevert); + await shouldFail.reverting(this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth })); }); }); diff --git a/test/crowdsale/MintedCrowdsale.test.js b/test/crowdsale/MintedCrowdsale.test.js index a3c846b2d..0b95f9ab8 100644 --- a/test/crowdsale/MintedCrowdsale.test.js +++ b/test/crowdsale/MintedCrowdsale.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeMintedCrowdsale } = require('./MintedCrowdsale.behavior'); const { ether } = require('../helpers/ether'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -35,11 +35,11 @@ contract('MintedCrowdsale', function ([_, deployer, investor, wallet, purchaser] }); it('rejects bare payments', async function () { - await assertRevert(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.send(value)); }); it('rejects token purchases', async function () { - await assertRevert(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); }); }); }); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 866e4da15..723cb1fca 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -1,7 +1,6 @@ const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -51,7 +50,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { - await expectThrow(this.crowdsale.withdrawTokens(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); }); context('after closing time', function () { @@ -67,7 +66,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { it('rejects multiple withdrawals', async function () { await this.crowdsale.withdrawTokens(investor); - await expectThrow(this.crowdsale.withdrawTokens(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); }); }); }); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 77e0bfebb..6b863abad 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,8 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; @@ -35,11 +34,8 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('rejects a goal of zero', async function () { - await expectThrow( - RefundableCrowdsaleImpl.new( - this.openingTime, this.closingTime, rate, wallet, this.token.address, 0, - ), - EVMRevert, + await shouldFail.reverting( + RefundableCrowdsaleImpl.new(this.openingTime, this.closingTime, rate, wallet, this.token.address, 0) ); }); @@ -54,7 +50,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon context('before opening time', function () { it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); }); @@ -64,7 +60,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); context('with unreached goal', function () { @@ -99,7 +95,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('denies refunds', async function () { - await expectThrow(this.crowdsale.claimRefund(investor), EVMRevert); + await shouldFail.reverting(this.crowdsale.claimRefund(investor)); }); it('forwards funds to wallet', async function () { diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index cfbc3d3cf..eb2a9bf51 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -1,8 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); const BigNumber = web3.BigNumber; @@ -31,15 +30,15 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { }); it('rejects an opening time in the past', async function () { - await expectThrow(TimedCrowdsaleImpl.new( + await shouldFail.reverting(TimedCrowdsaleImpl.new( (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address - ), EVMRevert); + )); }); it('rejects a closing time before the opening time', async function () { - await expectThrow(TimedCrowdsaleImpl.new( + await shouldFail.reverting(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address - ), EVMRevert); + )); }); context('with crowdsale', function () { @@ -60,8 +59,8 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { describe('accepting payments', function () { it('should reject payments before start', async function () { (await this.crowdsale.isOpen()).should.equal(false); - await expectThrow(this.crowdsale.send(value), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { from: purchaser, value: value }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: purchaser, value: value })); }); it('should accept payments after start', async function () { @@ -73,8 +72,8 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { it('should reject payments after end', async function () { await time.increaseTo(this.afterClosingTime); - await expectThrow(this.crowdsale.send(value), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(value)); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser })); }); }); }); diff --git a/test/drafts/ERC20Migrator.test.js b/test/drafts/ERC20Migrator.test.js index 608dce860..92763a219 100644 --- a/test/drafts/ERC20Migrator.test.js +++ b/test/drafts/ERC20Migrator.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const ERC20Mock = artifacts.require('ERC20Mock'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20Migrator = artifacts.require('ERC20Migrator'); @@ -14,7 +15,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { const totalSupply = 200; it('reverts with a null legacy token address', async function () { - await assertRevert(ERC20Migrator.new(ZERO_ADDRESS)); + await shouldFail.reverting(ERC20Migrator.new(ZERO_ADDRESS)); }); describe('with tokens and migrator', function () { @@ -30,11 +31,11 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { describe('beginMigration', function () { it('reverts with a null new token address', async function () { - await assertRevert(this.migrator.beginMigration(ZERO_ADDRESS)); + await shouldFail.reverting(this.migrator.beginMigration(ZERO_ADDRESS)); }); it('reverts if not a minter of the token', async function () { - await assertRevert(this.migrator.beginMigration(this.newToken.address)); + await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); }); it('succeeds if it is a minter of the token', async function () { @@ -45,7 +46,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { it('reverts the second time it is called', async function () { await this.newToken.addMinter(this.migrator.address); await this.migrator.beginMigration(this.newToken.address); - await assertRevert(this.migrator.beginMigration(this.newToken.address)); + await shouldFail.reverting(this.migrator.beginMigration(this.newToken.address)); }); }); @@ -145,7 +146,7 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { const amount = baseAmount + 1; it('reverts', async function () { - await assertRevert(this.migrator.migrate(owner, amount)); + await shouldFail.reverting(this.migrator.migrate(owner, amount)); }); }); }); diff --git a/test/drafts/SignatureBouncer.test.js b/test/drafts/SignatureBouncer.test.js index c234687fc..e1bb294f3 100644 --- a/test/drafts/SignatureBouncer.test.js +++ b/test/drafts/SignatureBouncer.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { getSignFor } = require('../helpers/sign'); const { shouldBehaveLikePublicRole } = require('../access/roles/PublicRole.behavior'); @@ -36,19 +36,19 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: anyone }) ); }); it('does not allow valid signature for method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignature(this.signFor(authorizedUser, 'onlyWithValidSignature'), { from: authorizedUser }) ); @@ -63,13 +63,13 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature with correct method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature with correct method for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod( this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: anyone } ) @@ -77,14 +77,14 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid method signature with incorrect method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser, 'theWrongMethod'), { from: authorizedUser }) ); }); it('does not allow valid non-method signature method for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser), { from: authorizedUser }) ); }); @@ -98,13 +98,13 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow invalid signature with correct method and data for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser }) ); }); it('does not allow valid signature with correct method and incorrect data for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10, this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: authorizedUser } @@ -113,7 +113,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid signature with correct method and data for other sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: anyone } @@ -122,7 +122,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow valid non-method signature for sender', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, this.signFor(authorizedUser), { from: authorizedUser } ) @@ -130,7 +130,7 @@ contract('SignatureBouncer', function ([_, signer, otherSigner, anyone, authoriz }); it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () { - await assertRevert( + await shouldFail.reverting( this.sigBouncer.tooShortMsgData({ from: authorizedUser }) ); }); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index 303ddf704..da367c970 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -1,9 +1,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); -const { assertRevert } = require('../helpers/assertRevert'); const { ethGetBalance } = require('../helpers/web3'); const BigNumber = web3.BigNumber; @@ -53,14 +51,8 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { }); it('should not accept payments before start', async function () { - await expectThrow( - this.crowdsale.send(ether(1)), - EVMRevert, - ); - await expectThrow( - this.crowdsale.buyTokens(investor, { from: investor, value: ether(1) }), - EVMRevert, - ); + await shouldFail.reverting(this.crowdsale.send(ether(1))); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { from: investor, value: ether(1) })); }); it('should accept payments during the sale', async function () { @@ -76,14 +68,14 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { it('should reject payments after end', async function () { await time.increaseTo(this.afterClosingTime); - await expectThrow(this.crowdsale.send(ether(1)), EVMRevert); - await expectThrow(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor }), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(ether(1))); + await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: ether(1), from: investor })); }); it('should reject payments over cap', async function () { await time.increaseTo(this.openingTime); await this.crowdsale.send(CAP); - await expectThrow(this.crowdsale.send(1), EVMRevert); + await shouldFail.reverting(this.crowdsale.send(1)); }); it('should allow finalization and transfer funds to wallet if the goal is reached', async function () { @@ -117,7 +109,7 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { const HIGH_GOAL = ether(30); it('creation reverts', async function () { - await assertRevert(SampleCrowdsale.new( + await shouldFail.reverting(SampleCrowdsale.new( this.openingTime, this.closingTime, RATE, wallet, CAP, this.token.address, HIGH_GOAL )); }); diff --git a/test/helpers/EVMRevert.js b/test/helpers/EVMRevert.js deleted file mode 100644 index cb0c8e02e..000000000 --- a/test/helpers/EVMRevert.js +++ /dev/null @@ -1,5 +0,0 @@ -const EVMRevert = 'revert'; - -module.exports = { - EVMRevert, -}; diff --git a/test/helpers/EVMThrow.js b/test/helpers/EVMThrow.js deleted file mode 100644 index afe21d277..000000000 --- a/test/helpers/EVMThrow.js +++ /dev/null @@ -1,5 +0,0 @@ -const EVMThrow = 'invalid opcode'; - -module.exports = { - EVMThrow, -}; diff --git a/test/helpers/assertJump.js b/test/helpers/assertJump.js deleted file mode 100644 index 979307088..000000000 --- a/test/helpers/assertJump.js +++ /dev/null @@ -1,15 +0,0 @@ -const should = require('chai') - .should(); - -async function assertJump (promise) { - try { - await promise; - should.fail('Expected invalid opcode not received'); - } catch (error) { - error.message.should.include('invalid opcode', `Expected "invalid opcode", got ${error} instead`); - } -} - -module.exports = { - assertJump, -}; diff --git a/test/helpers/assertRevert.js b/test/helpers/assertRevert.js deleted file mode 100644 index 3d1aa2e16..000000000 --- a/test/helpers/assertRevert.js +++ /dev/null @@ -1,16 +0,0 @@ -const should = require('chai') - .should(); - -async function assertRevert (promise) { - try { - await promise; - } catch (error) { - error.message.should.include('revert', `Expected "revert", got ${error} instead`); - return; - } - should.fail('Expected revert not received'); -} - -module.exports = { - assertRevert, -}; diff --git a/test/helpers/expectThrow.js b/test/helpers/expectThrow.js deleted file mode 100644 index f46a981c8..000000000 --- a/test/helpers/expectThrow.js +++ /dev/null @@ -1,28 +0,0 @@ -const should = require('chai') - .should(); - -async function expectThrow (promise, message) { - try { - await promise; - } catch (error) { - // Message is an optional parameter here - if (message) { - error.message.should.include(message, 'Expected \'' + message + '\', got \'' + error + '\' instead'); - return; - } else { - // TODO: Check jump destination to destinguish between a throw - // and an actual invalid jump. - // TODO: When we contract A calls contract B, and B throws, instead - // of an 'invalid jump', we get an 'out of gas' error. How do - // we distinguish this from an actual out of gas event? (The - // ganache log actually show an 'invalid jump' event.) - error.message.should.match(/[invalid opcode|out of gas|revert]/, 'Expected throw, got \'' + error + '\' instead'); - return; - } - } - should.fail('Expected throw not received'); -} - -module.exports = { - expectThrow, -}; diff --git a/test/helpers/shouldFail.js b/test/helpers/shouldFail.js new file mode 100644 index 000000000..45e72f921 --- /dev/null +++ b/test/helpers/shouldFail.js @@ -0,0 +1,31 @@ +const should = require('chai') + .should(); + +async function shouldFailWithMessage (promise, message) { + try { + await promise; + } catch (error) { + error.message.should.include(message, 'Wrong failure type'); + return; + } + + should.fail(`Expected '${message}' failure not received`); +} + +async function reverting (promise) { + await shouldFailWithMessage(promise, 'revert'); +} + +async function throwing (promise) { + await shouldFailWithMessage(promise, 'invalid opcode'); +} + +async function outOfGas (promise) { + await shouldFailWithMessage(promise, 'out of gas'); +} + +module.exports = { + reverting, + throwing, + outOfGas, +}; diff --git a/test/introspection/ERC165.test.js b/test/introspection/ERC165.test.js index dc04edaa2..0dc2f8471 100644 --- a/test/introspection/ERC165.test.js +++ b/test/introspection/ERC165.test.js @@ -1,5 +1,5 @@ const { shouldSupportInterfaces } = require('./SupportsInterface.behavior'); -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const ERC165Mock = artifacts.require('ERC165Mock'); @@ -12,7 +12,7 @@ contract('ERC165', function () { }); it('does not allow 0xffffffff', async function () { - await assertRevert( + await shouldFail.reverting( this.mock.registerInterface(0xffffffff) ); }); diff --git a/test/library/ECDSA.test.js b/test/library/ECDSA.test.js index f8d333a5f..b07178b20 100644 --- a/test/library/ECDSA.test.js +++ b/test/library/ECDSA.test.js @@ -1,5 +1,5 @@ const { signMessage, toEthSignedMessageHash } = require('../helpers/sign'); -const { expectThrow } = require('../helpers/expectThrow'); +const shouldFail = require('../helpers/shouldFail'); const ECDSAMock = artifacts.require('ECDSAMock'); @@ -113,7 +113,7 @@ contract('ECDSA', function ([_, anyone]) { it.skip('reverts', async function () { // Create the signature const signature = signMessage(anyone, TEST_MESSAGE); - await expectThrow( + await shouldFail.reverting( this.ecdsa.recover(TEST_MESSAGE.substring(2), signature) ); }); diff --git a/test/lifecycle/Pausable.test.js b/test/lifecycle/Pausable.test.js index 2ae4c90d7..a7f6d637d 100644 --- a/test/lifecycle/Pausable.test.js +++ b/test/lifecycle/Pausable.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const PausableMock = artifacts.require('PausableMock'); @@ -37,7 +37,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('cannot take drastic measure in non-pause', async function () { - await assertRevert(this.pausable.drasticMeasure({ from: anyone })); + await shouldFail.reverting(this.pausable.drasticMeasure({ from: anyone })); (await this.pausable.drasticMeasureTaken()).should.equal(false); }); @@ -48,7 +48,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when pausing from non-pauser', async function () { - await assertRevert(this.pausable.pause({ from: anyone })); + await shouldFail.reverting(this.pausable.pause({ from: anyone })); }); context('when paused', function () { @@ -61,7 +61,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('cannot perform normal process in pause', async function () { - await assertRevert(this.pausable.normalProcess({ from: anyone })); + await shouldFail.reverting(this.pausable.normalProcess({ from: anyone })); }); it('can take a drastic measure in a pause', async function () { @@ -70,7 +70,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when re-pausing', async function () { - await assertRevert(this.pausable.pause({ from: pauser })); + await shouldFail.reverting(this.pausable.pause({ from: pauser })); }); describe('unpausing', function () { @@ -80,7 +80,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('reverts when unpausing from non-pauser', async function () { - await assertRevert(this.pausable.unpause({ from: anyone })); + await shouldFail.reverting(this.pausable.unpause({ from: anyone })); }); context('when unpaused', function () { @@ -99,11 +99,11 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('should prevent drastic measure', async function () { - await assertRevert(this.pausable.drasticMeasure({ from: anyone })); + await shouldFail.reverting(this.pausable.drasticMeasure({ from: anyone })); }); it('reverts when re-unpausing', async function () { - await assertRevert(this.pausable.unpause({ from: pauser })); + await shouldFail.reverting(this.pausable.unpause({ from: pauser })); }); }); }); diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index 56cedeb84..dcbb4fbb6 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { MAX_UINT256 } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -25,7 +25,7 @@ contract('SafeMath', function () { const a = MAX_UINT256; const b = new BigNumber(1); - await assertRevert(this.safeMath.add(a, b)); + await shouldFail.reverting(this.safeMath.add(a, b)); }); }); @@ -41,7 +41,7 @@ contract('SafeMath', function () { const a = new BigNumber(1234); const b = new BigNumber(5678); - await assertRevert(this.safeMath.sub(a, b)); + await shouldFail.reverting(this.safeMath.sub(a, b)); }); }); @@ -64,7 +64,7 @@ contract('SafeMath', function () { const a = MAX_UINT256; const b = new BigNumber(2); - await assertRevert(this.safeMath.mul(a, b)); + await shouldFail.reverting(this.safeMath.mul(a, b)); }); }); @@ -80,7 +80,7 @@ contract('SafeMath', function () { const a = new BigNumber(5678); const b = new BigNumber(0); - await assertRevert(this.safeMath.div(a, b)); + await shouldFail.reverting(this.safeMath.div(a, b)); }); }); @@ -119,7 +119,7 @@ contract('SafeMath', function () { const a = new BigNumber(5678); const b = new BigNumber(0); - await assertRevert(this.safeMath.mod(a, b)); + await shouldFail.reverting(this.safeMath.mod(a, b)); }); }); }); diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index 1e2fd7564..dd6007cef 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -22,11 +21,11 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('should prevent non-owners from transfering', async function () { - await expectThrow(this.ownable.transferOwnership(anyone, { from: anyone }), EVMRevert); + await shouldFail.reverting(this.ownable.transferOwnership(anyone, { from: anyone })); }); it('should guard ownership against stuck state', async function () { - await expectThrow(this.ownable.transferOwnership(null, { from: owner }), EVMRevert); + await shouldFail.reverting(this.ownable.transferOwnership(null, { from: owner })); }); it('loses owner after renouncement', async function () { @@ -37,7 +36,7 @@ function shouldBehaveLikeOwnable (owner, [anyone]) { }); it('should prevent non-owners from renouncement', async function () { - await expectThrow(this.ownable.renounceOwnership({ from: anyone }), EVMRevert); + await shouldFail.reverting(this.ownable.renounceOwnership({ from: anyone })); }); }); } diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 31676be79..55283963b 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,5 +1,6 @@ -const { assertRevert } = require('../helpers/assertRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../helpers/constants'); + const SecondaryMock = artifacts.require('SecondaryMock'); require('chai') @@ -20,7 +21,7 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when anyone calls onlyPrimary functions', async function () { - await assertRevert(this.secondary.onlyPrimaryMock({ from: anyone })); + await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: anyone })); }); }); @@ -31,11 +32,11 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when transfering to the null address', async function () { - await assertRevert(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary })); + await shouldFail.reverting(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary })); }); it('reverts when called by anyone', async function () { - await assertRevert(this.secondary.transferPrimary(newPrimary, { from: anyone })); + await shouldFail.reverting(this.secondary.transferPrimary(newPrimary, { from: anyone })); }); context('with new primary', function () { @@ -48,7 +49,7 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { }); it('reverts when the old primary account calls onlyPrimary functions', async function () { - await assertRevert(this.secondary.onlyPrimaryMock({ from: primary })); + await shouldFail.reverting(this.secondary.onlyPrimaryMock({ from: primary })); }); }); }); diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/ConditionalEscrow.test.js index 03eed68f7..bfb38dd86 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/ConditionalEscrow.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); + +const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -34,7 +34,7 @@ contract('ConditionalEscrow', function ([_, owner, payee, ...otherAccounts]) { it('reverts on withdrawals', async function () { await this.escrow.deposit(payee, { from: owner, value: amount }); - await expectThrow(this.escrow.withdraw(payee, { from: owner }), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(payee, { from: owner })); }); }); }); diff --git a/test/payment/Escrow.behavior.js b/test/payment/Escrow.behavior.js index 9769291e1..c724c5395 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/Escrow.behavior.js @@ -1,6 +1,5 @@ const expectEvent = require('../helpers/expectEvent'); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const { ethGetBalance } = require('../helpers/web3'); const { ether } = require('../helpers/ether'); @@ -28,7 +27,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('only the primary account can deposit', async function () { - await expectThrow(this.escrow.deposit(payee1, { from: payee2 }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(payee1, { from: payee2 })); }); it('emits a deposited event', async function () { @@ -80,7 +79,7 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { }); it('only the primary account can withdraw', async function () { - await expectThrow(this.escrow.withdraw(payee1, { from: payee1 }), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(payee1, { from: payee1 })); }); it('emits a withdrawn event', async function () { diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index a3d669d69..123da9d82 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert'); +const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const { ethGetBalance } = require('../helpers/web3'); const { ether } = require('../helpers/ether'); @@ -18,7 +17,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee const refundees = [refundee1, refundee2]; it('requires a non-null beneficiary', async function () { - await expectThrow( + await shouldFail.reverting( RefundEscrow.new(ZERO_ADDRESS, { from: primary }) ); }); @@ -42,17 +41,17 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('does not refund refundees', async function () { await this.escrow.deposit(refundee1, { from: primary, value: amount }); - await expectThrow(this.escrow.withdraw(refundee1), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(refundee1)); }); it('does not allow beneficiary withdrawal', async function () { await this.escrow.deposit(refundee1, { from: primary, value: amount }); - await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert); + await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); }); }); it('only the primary account can enter closed state', async function () { - await expectThrow(this.escrow.close({ from: beneficiary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: beneficiary })); const { logs } = await this.escrow.close({ from: primary }); expectEvent.inLogs(logs, 'Closed'); @@ -66,11 +65,11 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('rejects deposits', async function () { - await expectThrow(this.escrow.deposit(refundee1, { from: primary, value: amount }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); }); it('does not refund refundees', async function () { - await expectThrow(this.escrow.withdraw(refundee1), EVMRevert); + await shouldFail.reverting(this.escrow.withdraw(refundee1)); }); it('allows beneficiary withdrawal', async function () { @@ -82,16 +81,16 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('prevents entering the refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); }); it('prevents re-entering the closed state', async function () { - await expectThrow(this.escrow.close({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: primary })); }); }); it('only the primary account can enter refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: beneficiary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: beneficiary })); const { logs } = await this.escrow.enableRefunds({ from: primary }); expectEvent.inLogs(logs, 'RefundsEnabled'); @@ -105,7 +104,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('rejects deposits', async function () { - await expectThrow(this.escrow.deposit(refundee1, { from: primary, value: amount }), EVMRevert); + await shouldFail.reverting(this.escrow.deposit(refundee1, { from: primary, value: amount })); }); it('refunds refundees', async function () { @@ -119,15 +118,15 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('does not allow beneficiary withdrawal', async function () { - await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert); + await shouldFail.reverting(this.escrow.beneficiaryWithdraw()); }); it('prevents entering the closed state', async function () { - await expectThrow(this.escrow.close({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.close({ from: primary })); }); it('prevents re-entering the refund state', async function () { - await expectThrow(this.escrow.enableRefunds({ from: primary }), EVMRevert); + await shouldFail.reverting(this.escrow.enableRefunds({ from: primary })); }); }); }); diff --git a/test/payment/SplitPayment.test.js b/test/payment/SplitPayment.test.js index c4a720fb9..6a10a5131 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/SplitPayment.test.js @@ -9,35 +9,34 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const { expectThrow } = require('../helpers/expectThrow'); -const { EVMRevert } = require('../helpers/EVMRevert.js'); +const shouldFail = require('../helpers/shouldFail'); const SplitPayment = artifacts.require('SplitPayment'); contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { const amount = ether(1.0); it('rejects an empty set of payees', async function () { - await expectThrow(SplitPayment.new([], []), EVMRevert); + await shouldFail.reverting(SplitPayment.new([], [])); }); it('rejects more payees than shares', async function () { - await expectThrow(SplitPayment.new([payee1, payee2, payee3], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2, payee3], [20, 30])); }); it('rejects more shares than payees', async function () { - await expectThrow(SplitPayment.new([payee1, payee2], [20, 30, 40]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 30, 40])); }); it('rejects null payees', async function () { - await expectThrow(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30])); }); it('rejects zero-valued shares', async function () { - await expectThrow(SplitPayment.new([payee1, payee2], [20, 0]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 0])); }); it('rejects repeated payees', async function () { - await expectThrow(SplitPayment.new([payee1, payee1], [20, 30]), EVMRevert); + await shouldFail.reverting(SplitPayment.new([payee1, payee1], [20, 30])); }); context('once deployed', function () { @@ -74,12 +73,12 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, }); it('should throw if no funds to claim', async function () { - await expectThrow(this.contract.release(payee1), EVMRevert); + await shouldFail.reverting(this.contract.release(payee1)); }); it('should throw if non-payee want to claim', async function () { await sendEther(payer1, this.contract.address, amount); - await expectThrow(this.contract.release(nonpayee1), EVMRevert); + await shouldFail.reverting(this.contract.release(nonpayee1)); }); it('should distribute funds to payees', async function () { diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index e224de942..d60e9130c 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -43,7 +43,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transfer(to, amount, { from: owner })); + await shouldFail.reverting(this.token.transfer(to, amount, { from: owner })); }); }); @@ -74,7 +74,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const to = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.transfer(to, 100, { from: owner })); + await shouldFail.reverting(this.token.transfer(to, 100, { from: owner })); }); }); }); @@ -157,7 +157,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.approve(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.approve(spender, amount, { from: owner })); }); }); }); @@ -205,7 +205,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -219,7 +219,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 100; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); @@ -227,7 +227,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = 101; it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -242,7 +242,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('reverts', async function () { - await assertRevert(this.token.transferFrom(owner, to, amount, { from: spender })); + await shouldFail.reverting(this.token.transferFrom(owner, to, amount, { from: spender })); }); }); }); @@ -254,7 +254,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { function shouldDecreaseApproval (amount) { describe('when there was no approved amount before', function () { it('reverts', async function () { - await assertRevert(this.token.decreaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: owner })); }); }); @@ -287,7 +287,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('reverts when more than the full allowance is removed', async function () { - await assertRevert(this.token.decreaseAllowance(spender, approvedAmount + 1, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, approvedAmount + 1, { from: owner })); }); }); } @@ -310,7 +310,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.decreaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.decreaseAllowance(spender, amount, { from: owner })); }); }); }); @@ -392,7 +392,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const spender = ZERO_ADDRESS; it('reverts', async function () { - await assertRevert(this.token.increaseAllowance(spender, amount, { from: owner })); + await shouldFail.reverting(this.token.increaseAllowance(spender, amount, { from: owner })); }); }); }); @@ -402,7 +402,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const amount = new BigNumber(50); it('rejects a null account', async function () { - await assertRevert(this.token.mint(ZERO_ADDRESS, amount)); + await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, amount)); }); describe('for a non null account', function () { @@ -435,12 +435,12 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { const initialSupply = new BigNumber(100); it('rejects a null account', async function () { - await assertRevert(this.token.burn(ZERO_ADDRESS, 1)); + await shouldFail.reverting(this.token.burn(ZERO_ADDRESS, 1)); }); describe('for a non null account', function () { it('rejects burning more than balance', async function () { - await assertRevert(this.token.burn(owner, initialSupply.plus(1))); + await shouldFail.reverting(this.token.burn(owner, initialSupply.plus(1))); }); const describeBurn = function (description, amount) { @@ -487,16 +487,16 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { }); it('rejects a null account', async function () { - await assertRevert(this.token.burnFrom(ZERO_ADDRESS, 1)); + await shouldFail.reverting(this.token.burnFrom(ZERO_ADDRESS, 1)); }); describe('for a non null account', function () { it('rejects burning more than allowance', async function () { - await assertRevert(this.token.burnFrom(owner, allowance.plus(1))); + await shouldFail.reverting(this.token.burnFrom(owner, allowance.plus(1))); }); it('rejects burning more than balance', async function () { - await assertRevert(this.token.burnFrom(owner, initialSupply.plus(1))); + await shouldFail.reverting(this.token.burnFrom(owner, initialSupply.plus(1))); }); const describeBurnFrom = function (description, amount) { diff --git a/test/token/ERC20/ERC20Capped.test.js b/test/token/ERC20/ERC20Capped.test.js index 45558a162..dbb35e23b 100644 --- a/test/token/ERC20/ERC20Capped.test.js +++ b/test/token/ERC20/ERC20Capped.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ether } = require('../../helpers/ether'); const { shouldBehaveLikeERC20Mintable } = require('./behaviors/ERC20Mintable.behavior'); const { shouldBehaveLikeERC20Capped } = require('./behaviors/ERC20Capped.behavior'); @@ -9,7 +9,7 @@ contract('ERC20Capped', function ([_, minter, ...otherAccounts]) { const cap = ether(1000); it('requires a non-zero cap', async function () { - await assertRevert( + await shouldFail.reverting( ERC20Capped.new(0, { from: minter }) ); }); diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index a524e2442..05a0532ed 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -1,5 +1,5 @@ const expectEvent = require('../../helpers/expectEvent'); -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const ERC20PausableMock = artifacts.require('ERC20PausableMock'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); @@ -41,7 +41,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA }); it('reverts', async function () { - await assertRevert(this.token.pause({ from })); + await shouldFail.reverting(this.token.pause({ from })); }); }); }); @@ -50,7 +50,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA const from = anotherAccount; it('reverts', async function () { - await assertRevert(this.token.pause({ from })); + await shouldFail.reverting(this.token.pause({ from })); }); }); }); @@ -78,7 +78,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA describe('when the token is unpaused', function () { it('reverts', async function () { - await assertRevert(this.token.unpause({ from })); + await shouldFail.reverting(this.token.unpause({ from })); }); }); }); @@ -87,7 +87,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA const from = anotherAccount; it('reverts', async function () { - await assertRevert(this.token.unpause({ from })); + await shouldFail.reverting(this.token.unpause({ from })); }); }); }); @@ -133,7 +133,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.transfer(recipient, 100, { from: pauser })); + await shouldFail.reverting(this.token.transfer(recipient, 100, { from: pauser })); }); }); @@ -156,7 +156,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.approve(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.approve(anotherAccount, 40, { from: pauser })); }); }); @@ -185,7 +185,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer from when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.transferFrom(pauser, recipient, 40, { from: anotherAccount })); + await shouldFail.reverting(this.token.transferFrom(pauser, recipient, 40, { from: anotherAccount })); }); }); @@ -212,7 +212,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to transfer when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.decreaseAllowance(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.decreaseAllowance(anotherAccount, 40, { from: pauser })); }); }); @@ -239,7 +239,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA it('reverts when trying to increase approval when paused', async function () { await this.token.pause({ from: pauser }); - await assertRevert(this.token.increaseAllowance(anotherAccount, 40, { from: pauser })); + await shouldFail.reverting(this.token.increaseAllowance(anotherAccount, 40, { from: pauser })); }); }); }); diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index 6d61a2037..b6c87554b 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../../helpers/expectThrow'); -const { EVMRevert } = require('../../helpers/EVMRevert'); +const shouldFail = require('../../helpers/shouldFail'); require('chai') .should(); @@ -12,15 +11,15 @@ contract('SafeERC20', function () { }); it('should throw on failed transfer', async function () { - await expectThrow(this.helper.doFailingTransfer(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingTransfer()); }); it('should throw on failed transferFrom', async function () { - await expectThrow(this.helper.doFailingTransferFrom(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingTransferFrom()); }); it('should throw on failed approve', async function () { - await expectThrow(this.helper.doFailingApprove(), EVMRevert); + await shouldFail.reverting(this.helper.doFailingApprove()); }); it('should not throw on succeeding transfer', async function () { diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index 04441fd1e..1816bf902 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -1,5 +1,5 @@ +const shouldFail = require('../../helpers/shouldFail'); const time = require('../../helpers/time'); -const { expectThrow } = require('../../helpers/expectThrow'); const BigNumber = web3.BigNumber; @@ -20,7 +20,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { it('rejects a release time in the past', async function () { const pastReleaseTime = (await time.latest()) - time.duration.years(1); - await expectThrow( + await shouldFail.reverting( TokenTimelock.new(this.token.address, beneficiary, pastReleaseTime) ); }); @@ -39,12 +39,12 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { }); it('cannot be released before time limit', async function () { - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); }); it('cannot be released just before time limit', async function () { await time.increaseTo(this.releaseTime - time.duration.seconds(3)); - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); }); it('can be released just after limit', async function () { @@ -62,7 +62,7 @@ contract('TokenTimelock', function ([_, minter, beneficiary]) { it('cannot be released twice', async function () { await time.increaseTo(this.releaseTime + time.duration.years(1)); await this.timelock.release(); - await expectThrow(this.timelock.release()); + await shouldFail.reverting(this.timelock.release()); (await this.token.balanceOf(beneficiary)).should.be.bignumber.equal(amount); }); }); diff --git a/test/token/ERC20/TokenVesting.test.js b/test/token/ERC20/TokenVesting.test.js index acfdb9adc..8fd767be1 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/token/ERC20/TokenVesting.test.js @@ -1,5 +1,4 @@ -const { expectThrow } = require('../../helpers/expectThrow'); -const { EVMRevert } = require('../../helpers/EVMRevert'); +const shouldFail = require('../../helpers/shouldFail'); const time = require('../../helpers/time'); const { ethGetBlock } = require('../../helpers/web3'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -29,13 +28,13 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { cliffDuration.should.be.gt(duration); - await expectThrow( + await shouldFail.reverting( TokenVesting.new(beneficiary, this.start, cliffDuration, duration, true, { from: owner }) ); }); it('requires a valid beneficiary', async function () { - await expectThrow( + await shouldFail.reverting( TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }) ); }); @@ -58,10 +57,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('cannot be released before cliff', async function () { - await expectThrow( - this.vesting.release(this.token.address), - EVMRevert, - ); + await shouldFail.reverting(this.vesting.release(this.token.address)); }); it('can be released after cliff', async function () { @@ -113,10 +109,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { beneficiary, this.start, this.cliffDuration, this.duration, false, { from: owner } ); - await expectThrow( - vesting.revoke(this.token.address, { from: owner }), - EVMRevert, - ); + await shouldFail.reverting(vesting.revoke(this.token.address, { from: owner })); }); it('should return the non-vested tokens when revoked by owner', async function () { @@ -148,10 +141,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { await this.vesting.revoke(this.token.address, { from: owner }); - await expectThrow( - this.vesting.revoke(this.token.address, { from: owner }), - EVMRevert, - ); + await shouldFail.reverting(this.vesting.revoke(this.token.address, { from: owner })); }); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 25af3254c..6e550afcb 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../../helpers/assertRevert'); +const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); @@ -42,7 +42,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = initialBalance + 1; it('reverts', async function () { - await assertRevert(this.token.burn(amount, { from: owner })); + await shouldFail.reverting(this.token.burn(amount, { from: owner })); }); }); }); @@ -88,7 +88,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = initialBalance + 1; it('reverts', async function () { await this.token.approve(burner, amount, { from: owner }); - await assertRevert(this.token.burnFrom(owner, amount, { from: burner })); + await shouldFail.reverting(this.token.burnFrom(owner, amount, { from: burner })); }); }); @@ -96,7 +96,7 @@ function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { const amount = 100; it('reverts', async function () { await this.token.approve(burner, amount - 1, { from: owner }); - await assertRevert(this.token.burnFrom(owner, amount, { from: burner })); + await shouldFail.reverting(this.token.burnFrom(owner, amount, { from: burner })); }); }); }); diff --git a/test/token/ERC20/behaviors/ERC20Capped.behavior.js b/test/token/ERC20/behaviors/ERC20Capped.behavior.js index 3c3ab7fbf..e61db5702 100644 --- a/test/token/ERC20/behaviors/ERC20Capped.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Capped.behavior.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('../../../helpers/expectThrow'); +const shouldFail = require('../../../helpers/shouldFail'); const BigNumber = web3.BigNumber; @@ -21,12 +21,12 @@ function shouldBehaveLikeERC20Capped (minter, [anyone], cap) { it('should fail to mint if the ammount exceeds the cap', async function () { await this.token.mint(anyone, cap.sub(1), { from }); - await expectThrow(this.token.mint(anyone, 100, { from })); + await shouldFail.reverting(this.token.mint(anyone, 100, { from })); }); it('should fail to mint after cap is reached', async function () { await this.token.mint(anyone, cap, { from }); - await expectThrow(this.token.mint(anyone, 1, { from })); + await shouldFail.reverting(this.token.mint(anyone, 1, { from })); }); }); } diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index f34504afc..bb8c0fe30 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../../helpers/assertRevert'); +const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); @@ -47,7 +47,7 @@ function shouldBehaveLikeERC20Mintable (minter, [anyone]) { const from = anyone; it('reverts', async function () { - await assertRevert(this.token.mint(anyone, amount, { from })); + await shouldFail.reverting(this.token.mint(anyone, amount, { from })); }); }); }); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index a18b6b437..aea385a99 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -1,6 +1,6 @@ const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); @@ -44,7 +44,7 @@ function shouldBehaveLikeERC721 ( context('when querying the zero address', function () { it('throws', async function () { - await assertRevert(this.token.balanceOf(0)); + await shouldFail.reverting(this.token.balanceOf(0)); }); }); }); @@ -62,7 +62,7 @@ function shouldBehaveLikeERC721 ( const tokenId = unknownTokenId; it('reverts', async function () { - await assertRevert(this.token.ownerOf(tokenId)); + await shouldFail.reverting(this.token.ownerOf(tokenId)); }); }); }); @@ -184,28 +184,28 @@ function shouldBehaveLikeERC721 ( context('when the address of the previous owner is incorrect', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, anyone, anyone, tokenId, { from: owner }) + await shouldFail.reverting(transferFunction.call(this, anyone, anyone, tokenId, { from: owner }) ); }); }); context('when the sender is not authorized for the token id', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, anyone, tokenId, { from: anyone }) + await shouldFail.reverting(transferFunction.call(this, owner, anyone, tokenId, { from: anyone }) ); }); }); context('when the given token ID does not exist', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner }) + await shouldFail.reverting(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner }) ); }); }); context('when the address to transfer the token to is the zero address', function () { it('reverts', async function () { - await assertRevert(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner })); + await shouldFail.reverting(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner })); }); }); }; @@ -274,7 +274,7 @@ function shouldBehaveLikeERC721 ( describe('with an invalid token id', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( transferFun.call( this, owner, @@ -299,21 +299,27 @@ function shouldBehaveLikeERC721 ( describe('to a receiver contract returning unexpected value', function () { it('reverts', async function () { const invalidReceiver = await ERC721ReceiverMock.new('0x42', false); - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); describe('to a receiver contract that throws', function () { it('reverts', async function () { const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true); - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); describe('to a contract that does not implement the required function', function () { it('reverts', async function () { const invalidReceiver = this.token; - await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })); + await shouldFail.reverting( + this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }) + ); }); }); }); @@ -400,7 +406,7 @@ function shouldBehaveLikeERC721 ( context('when the address that receives the approval is the owner', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( this.token.approve(owner, tokenId, { from: owner }) ); }); @@ -408,14 +414,14 @@ function shouldBehaveLikeERC721 ( context('when the sender does not own the given token ID', function () { it('reverts', async function () { - await assertRevert(this.token.approve(approved, tokenId, { from: anyone })); + await shouldFail.reverting(this.token.approve(approved, tokenId, { from: anyone })); }); }); context('when the sender is approved for the given token ID', function () { it('reverts', async function () { await this.token.approve(approved, tokenId, { from: owner }); - await assertRevert(this.token.approve(anotherApproved, tokenId, { from: approved })); + await shouldFail.reverting(this.token.approve(anotherApproved, tokenId, { from: approved })); }); }); @@ -431,7 +437,7 @@ function shouldBehaveLikeERC721 ( context('when the given token ID does not exist', function () { it('reverts', async function () { - await assertRevert(this.token.approve(approved, unknownTokenId, { from: operator })); + await shouldFail.reverting(this.token.approve(approved, unknownTokenId, { from: operator })); }); }); }); @@ -509,7 +515,7 @@ function shouldBehaveLikeERC721 ( context('when the operator is the owner', function () { it('reverts', async function () { - await assertRevert(this.token.setApprovalForAll(owner, true, { from: owner })); + await shouldFail.reverting(this.token.setApprovalForAll(owner, true, { from: owner })); }); }); }); diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index 30e4547c8..6789ca28a 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); @@ -69,13 +69,13 @@ contract('ERC721Full', function ([ it('burns all tokens', async function () { await this.token.burn(secondTokenId, { from: owner }); (await this.token.totalSupply()).toNumber().should.be.equal(0); - await assertRevert(this.token.tokenByIndex(0)); + await shouldFail.reverting(this.token.tokenByIndex(0)); }); }); describe('removeTokenFrom', function () { it('reverts if the correct owner is not passed', async function () { - await assertRevert( + await shouldFail.reverting( this.token.removeTokenFrom(anyone, firstTokenId, { from: owner }) ); }); @@ -86,7 +86,7 @@ contract('ERC721Full', function ([ }); it('has been removed', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 1)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 1)); }); it('adjusts token list', async function () { @@ -120,7 +120,7 @@ contract('ERC721Full', function ([ }); it('reverts when setting metadata for non existent token id', async function () { - await assertRevert(this.token.setTokenURI(nonExistentTokenId, sampleUri)); + await shouldFail.reverting(this.token.setTokenURI(nonExistentTokenId, sampleUri)); }); it('can burn token with metadata', async function () { @@ -134,7 +134,7 @@ contract('ERC721Full', function ([ }); it('reverts when querying metadata for non existent token id', async function () { - await assertRevert(this.token.tokenURI(nonExistentTokenId)); + await shouldFail.reverting(this.token.tokenURI(nonExistentTokenId)); }); }); @@ -153,13 +153,13 @@ contract('ERC721Full', function ([ describe('when the index is greater than or equal to the total tokens owned by the given address', function () { it('reverts', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 2)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 2)); }); }); describe('when the given address does not own any token', function () { it('reverts', async function () { - await assertRevert(this.token.tokenOfOwnerByIndex(another, 0)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(another, 0)); }); }); @@ -179,7 +179,7 @@ contract('ERC721Full', function ([ it('returns empty collection for original owner', async function () { (await this.token.balanceOf(owner)).toNumber().should.be.equal(0); - await assertRevert(this.token.tokenOfOwnerByIndex(owner, 0)); + await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 0)); }); }); }); @@ -193,7 +193,7 @@ contract('ERC721Full', function ([ }); it('should revert if index is greater than supply', async function () { - await assertRevert(this.token.tokenByIndex(2)); + await shouldFail.reverting(this.token.tokenByIndex(2)); }); [firstTokenId, secondTokenId].forEach(function (tokenId) { diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index a5141abca..1bb7d1bc7 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -52,13 +52,13 @@ function shouldBehaveLikeMintAndBurnERC721 ( describe('when the given owner address is the zero address', function () { it('reverts', async function () { - await assertRevert(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); + await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter })); }); }); describe('when the given token ID was already tracked by this contract', function () { it('reverts', async function () { - await assertRevert(this.token.mint(owner, firstTokenId, { from: minter })); + await shouldFail.reverting(this.token.mint(owner, firstTokenId, { from: minter })); }); }); }); @@ -82,7 +82,7 @@ function shouldBehaveLikeMintAndBurnERC721 ( }); it('burns the given token ID and adjusts the balance of the owner', async function () { - await assertRevert(this.token.ownerOf(tokenId)); + await shouldFail.reverting(this.token.ownerOf(tokenId)); (await this.token.balanceOf(owner)).should.be.bignumber.equal(1); }); @@ -104,14 +104,14 @@ function shouldBehaveLikeMintAndBurnERC721 ( context('getApproved', function () { it('reverts', async function () { - await assertRevert(this.token.getApproved(tokenId)); + await shouldFail.reverting(this.token.getApproved(tokenId)); }); }); }); describe('when the given token ID was not tracked by this contract', function () { it('reverts', async function () { - await assertRevert( + await shouldFail.reverting( this.token.burn(unknownTokenId, { from: creator }) ); }); diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index a7196d837..1d83608fa 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -1,4 +1,4 @@ -const { assertRevert } = require('../../helpers/assertRevert'); +const shouldFail = require('../../helpers/shouldFail'); const { sendTransaction } = require('../../helpers/sendTransaction'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -19,23 +19,23 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { }); it('reverts when trying to approve', async function () { - await assertRevert(this.token.approve(recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.approve(recipient, firstTokenId, { from: owner })); }); it('reverts when trying to setApprovalForAll', async function () { - await assertRevert(this.token.setApprovalForAll(operator, true, { from: owner })); + await shouldFail.reverting(this.token.setApprovalForAll(operator, true, { from: owner })); }); it('reverts when trying to transferFrom', async function () { - await assertRevert(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner })); }); it('reverts when trying to safeTransferFrom', async function () { - await assertRevert(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner })); + await shouldFail.reverting(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner })); }); it('reverts when trying to safeTransferFrom with data', async function () { - await assertRevert( + await shouldFail.reverting( sendTransaction( this.token, 'safeTransferFrom', diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 3952b2fcb..16706fe8e 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -1,4 +1,4 @@ -const { expectThrow } = require('../helpers/expectThrow'); +const shouldFail = require('../helpers/shouldFail'); const ReentrancyMock = artifacts.require('ReentrancyMock'); const ReentrancyAttack = artifacts.require('ReentrancyAttack'); @@ -16,7 +16,7 @@ contract('ReentrancyGuard', function () { it('should not allow remote callback', async function () { const attacker = await ReentrancyAttack.new(); - await expectThrow(this.reentrancyMock.countAndCall(attacker.address)); + await shouldFail.reverting(this.reentrancyMock.countAndCall(attacker.address)); }); // The following are more side-effects than intended behavior: @@ -24,10 +24,10 @@ contract('ReentrancyGuard', function () { // in the side-effects. it('should not allow local recursion', async function () { - await expectThrow(this.reentrancyMock.countLocalRecursive(10)); + await shouldFail.reverting(this.reentrancyMock.countLocalRecursive(10)); }); it('should not allow indirect local recursion', async function () { - await expectThrow(this.reentrancyMock.countThisRecursive(10)); + await shouldFail.reverting(this.reentrancyMock.countThisRecursive(10)); }); }); From 3266de1b5c81136c837707038e6b4e5fbd124973 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Wed, 10 Oct 2018 18:03:26 +0530 Subject: [PATCH 111/205] Non-constructor initialization removed (#1403) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1391 (cherry picked from commit da67e435b17e370f70bd2b63a2178334b52627ac) --- contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 6 +++++- contracts/lifecycle/Pausable.sol | 6 +++++- contracts/payment/SplitPayment.sol | 6 ++++-- contracts/utils/ReentrancyGuard.sol | 6 +++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index 37d205c8e..a640dca83 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -11,10 +11,14 @@ import "../validation/TimedCrowdsale.sol"; contract FinalizableCrowdsale is TimedCrowdsale { using SafeMath for uint256; - bool private _finalized = false; + bool private _finalized; event CrowdsaleFinalized(); + constructor() public { + _finalized = false; + } + /** * @return true if the crowdsale is finalized, false otherwise. */ diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 5287ecdcb..a6cae2a55 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -10,7 +10,11 @@ contract Pausable is PauserRole { event Paused(); event Unpaused(); - bool private _paused = false; + bool private _paused; + + constructor() public { + _paused = false; + } /** * @return true if the contract is paused, false otherwise. diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index 8bfcc7690..9c716e7ad 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -10,8 +10,8 @@ import "../math/SafeMath.sol"; contract SplitPayment { using SafeMath for uint256; - uint256 private _totalShares = 0; - uint256 private _totalReleased = 0; + uint256 private _totalShares; + uint256 private _totalReleased; mapping(address => uint256) private _shares; mapping(address => uint256) private _released; @@ -24,6 +24,8 @@ contract SplitPayment { require(payees.length == shares.length); require(payees.length > 0); + _totalShares = 0; + _totalReleased = 0; for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares[i]); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 63da3a99e..689c97205 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -9,7 +9,11 @@ pragma solidity ^0.4.24; contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation - uint256 private _guardCounter = 1; + uint256 private _guardCounter; + + constructor() public { + _guardCounter = 1; + } /** * @dev Prevents a contract from calling itself, directly or indirectly. From 5e82a64a0197c04088c341a1eb5d58875f026ed0 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 10 Oct 2018 12:06:22 -0600 Subject: [PATCH 112/205] Add a code style rule to make all state variables private (#1390) (cherry picked from commit 076cb7decd2a5823af23648105e2aa72888fb32a) --- CODE_STYLE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CODE_STYLE.md b/CODE_STYLE.md index 2eaac05c9..d3337b16f 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -16,6 +16,8 @@ Any exception or additions specific to our project are documented below. * Try to avoid acronyms and abbreviations. +* All state variables should be private. + * Private state variables should have an underscore prefix. ``` From 7ec607978474a2e6b8c650f3b385f958e48b655b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 10 Oct 2018 15:15:38 -0300 Subject: [PATCH 113/205] Fix typo in ARCHITECTURE.md (#1406) (cherry picked from commit eb92fd1f48ce5a1fc4c4afc15a414b6d29aa7891) --- contracts/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/ARCHITECTURE.md b/contracts/ARCHITECTURE.md index 3d0ebfdaa..bfb6cff8d 100644 --- a/contracts/ARCHITECTURE.md +++ b/contracts/ARCHITECTURE.md @@ -12,7 +12,7 @@ The following provides visibility into how OpenZeppelin's contracts are organize - **introspection** - An interface that can be used to make a contract comply with the ERC-165 standard as well as a contract that implements ERC-165 using a lookup table. - **lifecycle** - A collection of base contracts used to manage the existence and behavior of your contracts and their funds. - **math** - Libraries with safety checks on operations that throw on errors. -- **mocks** - A collection of abstract contracts that are primarily used for unit testing. They also serve as good usage examples and demonstrate how to combine contracts with inheritence when developing your own custom applications. +- **mocks** - A collection of abstract contracts that are primarily used for unit testing. They also serve as good usage examples and demonstrate how to combine contracts with inheritance when developing your own custom applications. - **ownership** - A collection of smart contracts that can be used to manage contract and token ownership - **payment** - A collection of smart contracts that can be used to manage payments through escrow arrangements, withdrawals, and claims. Includes support for both single payees and multiple payees. - **proposals** - A collection of smart contracts that reflect community Ethereum Improvement Proposals (EIPs). These contracts are under development and standardization. They are not recommended for production, but they are useful for experimentation with pending EIP standards. Go [here](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/ERC-Process) for more information. From 10a5864fdf291525d3c8b40f0f3928425a2970f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 10 Oct 2018 20:55:10 -0300 Subject: [PATCH 114/205] First test helpers tests (#1369) * Removed unused advanceToBlock. * Added advanceBlock tests. * Fixed advanceToBlock tests. * Added single argument tests. * Finished inLogs tests. * Fixed linter errors. * Fixed linter errors. (cherry picked from commit 9f822906b8e8e052bae7947d4c362fbabdd2c3ba) --- contracts/mocks/EventEmitter.sol | 62 ++++++ test/helpers/advanceToBlock.js | 12 -- test/helpers/test/advanceToBlock.test.js | 19 ++ test/helpers/test/expectEvent.test.js | 232 +++++++++++++++++++++++ 4 files changed, 313 insertions(+), 12 deletions(-) create mode 100644 contracts/mocks/EventEmitter.sol create mode 100644 test/helpers/test/advanceToBlock.test.js create mode 100644 test/helpers/test/expectEvent.test.js diff --git a/contracts/mocks/EventEmitter.sol b/contracts/mocks/EventEmitter.sol new file mode 100644 index 000000000..71582d9f5 --- /dev/null +++ b/contracts/mocks/EventEmitter.sol @@ -0,0 +1,62 @@ +pragma solidity ^0.4.24; + +contract EventEmitter { + event Argumentless(); + event ShortUint(uint8 value); + event ShortInt(int8 value); + event LongUint(uint256 value); + event LongInt(int256 value); + event Address(address value); + event Boolean(bool value); + event String(string value); + event LongUintBooleanString( + uint256 uintValue, + bool booleanValue, + string stringValue + ); + + function emitArgumentless() public { + emit Argumentless(); + } + + function emitShortUint(uint8 value) public { + emit ShortUint(value); + } + + function emitShortInt(int8 value) public { + emit ShortInt(value); + } + + function emitLongUint(uint256 value) public { + emit LongUint(value); + } + + function emitLongInt(int256 value) public { + emit LongInt(value); + } + + function emitAddress(address value) public { + emit Address(value); + } + + function emitBoolean(bool value) public { + emit Boolean(value); + } + + function emitString(string value) public { + emit String(value); + } + + function emitLongUintBooleanString( + uint256 uintValue, + bool booleanValue, + string stringValue) + public { + emit LongUintBooleanString(uintValue, booleanValue, stringValue); + } + + function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public { + emit LongUint(uintValue); + emit Boolean(boolValue); + } +} diff --git a/test/helpers/advanceToBlock.js b/test/helpers/advanceToBlock.js index 22e5467cc..225502022 100644 --- a/test/helpers/advanceToBlock.js +++ b/test/helpers/advanceToBlock.js @@ -10,18 +10,6 @@ function advanceBlock () { }); } -// Advances the block number so that the last mined block is `number`. -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(); - } -} - module.exports = { advanceBlock, - advanceToBlock, }; diff --git a/test/helpers/test/advanceToBlock.test.js b/test/helpers/test/advanceToBlock.test.js new file mode 100644 index 000000000..cd8f1c352 --- /dev/null +++ b/test/helpers/test/advanceToBlock.test.js @@ -0,0 +1,19 @@ +const advanceToBlock = require('../advanceToBlock'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('advanceToBlock', function () { + beforeEach(function () { + this.startingBlock = web3.eth.blockNumber; + }); + + describe('advanceBlock', function () { + it('increases the block number by one', async function () { + await advanceToBlock.advanceBlock(); + web3.eth.blockNumber.should.be.bignumber.equal(this.startingBlock + 1); + }); + }); +}); diff --git a/test/helpers/test/expectEvent.test.js b/test/helpers/test/expectEvent.test.js new file mode 100644 index 000000000..158a9f374 --- /dev/null +++ b/test/helpers/test/expectEvent.test.js @@ -0,0 +1,232 @@ +const expectEvent = require('../expectEvent'); +const EventEmitter = artifacts.require('EventEmitter'); + +const BigNumber = web3.BigNumber; +const should = require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('expectEvent', function () { + beforeEach(async function () { + this.emitter = await EventEmitter.new(); + }); + + describe('inLogs', function () { + describe('with no arguments', function () { + beforeEach(async function () { + ({ logs: this.logs } = await this.emitter.emitArgumentless()); + }); + + it('accepts emitted events', function () { + expectEvent.inLogs(this.logs, 'Argumentless'); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent')); + }); + }); + + describe('with single argument', function () { + context('short uint value', function () { + beforeEach(async function () { + this.value = 42; + ({ logs: this.logs } = await this.emitter.emitShortUint(this.value)); + }); + + it('accepts emitted events with correct JavaScript number', function () { + expectEvent.inLogs(this.logs, 'ShortUint', { value: this.value }); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'ShortUint', { value: new BigNumber(this.value) }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'ShortUint', { value: 23 })); + }); + }); + + context('short int value', function () { + beforeEach(async function () { + this.value = -42; + ({ logs: this.logs } = await this.emitter.emitShortInt(this.value)); + }); + + it('accepts emitted events with correct JavaScript number', function () { + expectEvent.inLogs(this.logs, 'ShortInt', { value: this.value }); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'ShortInt', { value: new BigNumber(this.value) }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'ShortInt', { value: -23 })); + }); + }); + + context('long uint value', function () { + beforeEach(async function () { + this.bigNumValue = new BigNumber('123456789012345678901234567890'); + ({ logs: this.logs } = await this.emitter.emitLongUint(this.bigNumValue)); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'LongUint', { value: this.bigNumValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 2300 })); + }); + }); + + context('long int value', function () { + beforeEach(async function () { + this.bigNumValue = new BigNumber('-123456789012345678901234567890'); + ({ logs: this.logs } = await this.emitter.emitLongInt(this.bigNumValue)); + }); + + it('accepts emitted events with correct BigNumber', function () { + expectEvent.inLogs(this.logs, 'LongInt', { value: this.bigNumValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongInt', { value: -2300 })); + }); + }); + + context('address value', function () { + beforeEach(async function () { + this.value = '0x811412068e9fbf25dc300a29e5e316f7122b282c'; + ({ logs: this.logs } = await this.emitter.emitAddress(this.value)); + }); + + it('accepts emitted events with correct address', function () { + expectEvent.inLogs(this.logs, 'Address', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => + expectEvent.inLogs(this.logs, 'Address', { value: '0x21d04e022e0b52b5d5bcf90b7f1aabf406be002d' }) + ); + }); + }); + + context('boolean value', function () { + beforeEach(async function () { + this.value = true; + ({ logs: this.logs } = await this.emitter.emitBoolean(this.value)); + }); + + it('accepts emitted events with correct address', function () { + expectEvent.inLogs(this.logs, 'Boolean', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false })); + }); + }); + + context('string value', function () { + beforeEach(async function () { + this.value = 'OpenZeppelin'; + ({ logs: this.logs } = await this.emitter.emitString(this.value)); + }); + + it('accepts emitted events with correct string', function () { + expectEvent.inLogs(this.logs, 'String', { value: this.value }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value })); + }); + + it('throws if an incorrect value is passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'String', { value: 'ClosedZeppelin' })); + }); + }); + }); + + describe('with multiple arguments', function () { + beforeEach(async function () { + this.uintValue = new BigNumber('123456789012345678901234567890'); + this.booleanValue = true; + this.stringValue = 'OpenZeppelin'; + ({ logs: this.logs } = + await this.emitter.emitLongUintBooleanString(this.uintValue, this.booleanValue, this.stringValue)); + }); + + it('accepts correct values', function () { + expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: this.stringValue, + }); + }); + + it('throws with correct values assigned to wrong arguments', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.booleanValue, booleanValue: this.uintValue, stringValue: this.stringValue, + })); + }); + + it('throws when any of the values is incorrect', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: 23, booleanValue: this.booleanValue, stringValue: this.stringValue, + })); + + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: false, stringValue: this.stringValue, + })); + + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', { + uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: 'ClosedZeppelin', + })); + }); + }); + + describe('with multiple events', function () { + beforeEach(async function () { + this.uintValue = 42; + this.booleanValue = true; + ({ logs: this.logs } = await this.emitter.emitLongUintAndBoolean(this.uintValue, this.booleanValue)); + }); + + it('accepts all emitted events with correct values', function () { + expectEvent.inLogs(this.logs, 'LongUint', { value: this.uintValue }); + expectEvent.inLogs(this.logs, 'Boolean', { value: this.booleanValue }); + }); + + it('throws if an unemitted event is requested', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.uintValue })); + }); + + it('throws if incorrect values are passed', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 23 })); + should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false })); + }); + }); + }); +}); From 2c40ffa011bce21d2466aeb307cafb6ac460680b Mon Sep 17 00:00:00 2001 From: Mikhail Melnik Date: Sat, 13 Oct 2018 01:13:36 +0300 Subject: [PATCH 115/205] Improve encapsulation on ERC165 and update code style guide (#1379) * use prefix underscore for internal state variables * make _supportedInterfaces private (cherry picked from commit 03dfb2965c6a607e216b110910f9fce1c43d8c94) --- CODE_STYLE.md | 1 + contracts/introspection/ERC165.sol | 2 +- contracts/mocks/ERC165/ERC165InterfacesSupported.sol | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CODE_STYLE.md b/CODE_STYLE.md index d3337b16f..0c00a15a5 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -23,6 +23,7 @@ Any exception or additions specific to our project are documented below. ``` contract TestContract { uint256 private _privateVar; + uint256 internal _internalVar; } ``` diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 1af78d111..0c8637297 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -18,7 +18,7 @@ contract ERC165 is IERC165 { /** * @dev a mapping of interface id to whether or not it's supported */ - mapping(bytes4 => bool) internal _supportedInterfaces; + mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 1a06e9d52..e41901a32 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -21,7 +21,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { /** * @dev a mapping of interface id to whether or not it's supported */ - mapping(bytes4 => bool) internal supportedInterfaces; + mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup @@ -41,7 +41,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { view returns (bool) { - return supportedInterfaces[interfaceId]; + return _supportedInterfaces[interfaceId]; } /** @@ -51,7 +51,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { internal { require(interfaceId != 0xffffffff); - supportedInterfaces[interfaceId] = true; + _supportedInterfaces[interfaceId] = true; } } From e990525c2e20bf7f254c34569d56f5719f8fe704 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Tue, 16 Oct 2018 19:07:04 +0530 Subject: [PATCH 116/205] RefundEscrow's events renamed (#1418) * fixes #1414 (cherry picked from commit 844a96d0b9419f5057bcae018b2a1974f075bc9d) --- contracts/payment/RefundEscrow.sol | 4 ++-- test/payment/RefundEscrow.test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/RefundEscrow.sol index c3770dbbb..3dfb3b965 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/RefundEscrow.sol @@ -11,7 +11,7 @@ import "./ConditionalEscrow.sol"; contract RefundEscrow is ConditionalEscrow { enum State { Active, Refunding, Closed } - event Closed(); + event RefundsClosed(); event RefundsEnabled(); State private _state; @@ -57,7 +57,7 @@ contract RefundEscrow is ConditionalEscrow { function close() public onlyPrimary { require(_state == State.Active); _state = State.Closed; - emit Closed(); + emit RefundsClosed(); } /** diff --git a/test/payment/RefundEscrow.test.js b/test/payment/RefundEscrow.test.js index 123da9d82..02a58a3b5 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/RefundEscrow.test.js @@ -54,7 +54,7 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee await shouldFail.reverting(this.escrow.close({ from: beneficiary })); const { logs } = await this.escrow.close({ from: primary }); - expectEvent.inLogs(logs, 'Closed'); + expectEvent.inLogs(logs, 'RefundsClosed'); }); context('closed state', function () { From 1b79b536cd6b03078b0945f3caf30bc324a09172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:20:33 -0300 Subject: [PATCH 117/205] Roles.add and remove now require pre-conditions on the account. (#1421) (cherry picked from commit 3bd30f7382ee4a03ea342ff6a90db8f0d486522e) --- contracts/access/Roles.sol | 4 ++++ test/access/Roles.test.js | 9 ++++----- test/access/roles/PublicRole.behavior.js | 13 ++++++------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index 930a62066..e3b97ddb7 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -14,6 +14,8 @@ library Roles { */ function add(Role storage role, address account) internal { require(account != address(0)); + require(!has(role, account)); + role.bearer[account] = true; } @@ -22,6 +24,8 @@ library Roles { */ function remove(Role storage role, address account) internal { require(account != address(0)); + require(has(role, account)); + role.bearer[account] = false; } diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 869217776..4a3c7b09f 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -29,10 +29,9 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { (await this.roles.has(anyone)).should.equal(false); }); - it('adds roles to an already-assigned account', async function () { + it('reverts when adding roles to an already assigned account', async function () { await this.roles.add(authorized); - await this.roles.add(authorized); - (await this.roles.has(authorized)).should.equal(true); + await shouldFail.reverting(this.roles.add(authorized)); }); it('reverts when adding roles to the null account', async function () { @@ -54,8 +53,8 @@ contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { (await this.roles.has(otherAuthorized)).should.equal(true); }); - it('doesn\'t revert when removing unassigned roles', async function () { - await this.roles.remove(anyone); + it('reverts when removing unassigned roles', async function () { + await shouldFail.reverting(this.roles.remove(anyone)); }); it('reverts when removing roles from the null account', async function () { diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index 57b94cf97..0ae8a19e6 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -52,9 +52,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Added`, { account: anyone }); }); - it('adds role to an already-assigned account', async function () { - await this.contract[`add${rolename}`](authorized, { from: authorized }); - (await this.contract[`is${rolename}`](authorized)).should.equal(true); + it('reverts when adding role to an already assigned account', async function () { + await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from: authorized })); }); it('reverts when adding role to the null account', async function () { @@ -74,8 +73,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); }); - it('doesn\'t revert when removing from an unassigned account', async function () { - await this.contract[`remove${rolename}`](anyone); + it('reverts when removing from an unassigned account', async function () { + await shouldFail.reverting(this.contract[`remove${rolename}`](anyone)); }); it('reverts when removing role from the null account', async function () { @@ -94,8 +93,8 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); }); - it('doesn\'t revert when renouncing unassigned role', async function () { - await this.contract[`renounce${rolename}`]({ from: anyone }); + it('reverts when renouncing unassigned role', async function () { + await shouldFail.reverting(this.contract[`renounce${rolename}`]({ from: anyone })); }); }); }); From 2514959f3446438c54f033f0172a06e9f6d175b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:20:55 -0300 Subject: [PATCH 118/205] Fixed a typo in a comment. (#1422) (cherry picked from commit 3341dd88994ee468c6b36a1affa4608dedab7a08) --- contracts/introspection/ERC165.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 0c8637297..60bcd53f3 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -42,7 +42,7 @@ contract ERC165 is IERC165 { } /** - * @dev private method for registering an interface + * @dev internal method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal From 5d596fc786fe915e1ccbd4b3bfc30316dba0adc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 16 Oct 2018 17:21:08 -0300 Subject: [PATCH 119/205] Added Math.sol docstrings. (#1423) (cherry picked from commit a3e312d133f9df1942b96b39cd007c883cd0331f) --- contracts/math/Math.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index d51a720c9..ffff83961 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -5,14 +5,25 @@ pragma solidity ^0.4.24; * @dev Assorted math operations */ library Math { + /** + * @dev Returns the largest of two numbers. + */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } + /** + * @dev Returns the smallest of two numbers. + */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } + /** + * @dev Calculates the average of two numbers. Since these are integers, + * averages of an even and odd number cannot be represented, and will be + * rounded down. + */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); From 1cf96ef0d11568eb66988a275e477eebd6a1e028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Winnicki?= Date: Wed, 17 Oct 2018 16:35:31 +0200 Subject: [PATCH 120/205] Make state variables private (#1426) * added function to renounce ownership * Make state variables private (#1411) (cherry picked from commit 03765e08b95afe9bd47544a4ec870ba37eb53420) --- contracts/token/ERC721/ERC721Metadata.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 8334160aa..4fb35543c 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -6,10 +6,10 @@ import "../../introspection/ERC165.sol"; contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Token name - string internal _name; + string private _name; // Token symbol - string internal _symbol; + string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; From 56806bb295b409145547c8bd5e48f2b2b137de09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 16:58:36 -0300 Subject: [PATCH 121/205] Now using hex for asm memory addresses. (#1429) (cherry picked from commit 2733cb4a411cf34e1a027ec5799298aa39ff549a) --- contracts/cryptography/ECDSA.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 3f0ad1bd2..71c0e41ed 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -33,9 +33,9 @@ library ECDSA { // currently is to use assembly. // solium-disable-next-line security/no-inline-assembly assembly { - r := mload(add(signature, 32)) - s := mload(add(signature, 64)) - v := byte(0, mload(add(signature, 96))) + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) } // Version of signature should be 27 or 28, but 0 and 1 are also possible versions From 26f9cc8e742ca59d007f3e5cc8e8c9a88fcdf149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 16:58:49 -0300 Subject: [PATCH 122/205] Moved some test files around to better reflect the directory layout. (#1428) (cherry picked from commit d8ab8a00f2cb3c066d17531aaf2403d0a5ba9c88) --- test/{library => cryptography}/ECDSA.test.js | 0 test/{library => cryptography}/MerkleProof.test.js | 0 test/{token/ERC20 => drafts}/TokenVesting.test.js | 8 ++++---- test/{library => math}/Math.test.js | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename test/{library => cryptography}/ECDSA.test.js (100%) rename test/{library => cryptography}/MerkleProof.test.js (100%) rename test/{token/ERC20 => drafts}/TokenVesting.test.js (96%) rename test/{library => math}/Math.test.js (100%) diff --git a/test/library/ECDSA.test.js b/test/cryptography/ECDSA.test.js similarity index 100% rename from test/library/ECDSA.test.js rename to test/cryptography/ECDSA.test.js diff --git a/test/library/MerkleProof.test.js b/test/cryptography/MerkleProof.test.js similarity index 100% rename from test/library/MerkleProof.test.js rename to test/cryptography/MerkleProof.test.js diff --git a/test/token/ERC20/TokenVesting.test.js b/test/drafts/TokenVesting.test.js similarity index 96% rename from test/token/ERC20/TokenVesting.test.js rename to test/drafts/TokenVesting.test.js index 8fd767be1..37864fbca 100644 --- a/test/token/ERC20/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -1,7 +1,7 @@ -const shouldFail = require('../../helpers/shouldFail'); -const time = require('../../helpers/time'); -const { ethGetBlock } = require('../../helpers/web3'); -const { ZERO_ADDRESS } = require('../../helpers/constants'); +const shouldFail = require('../helpers/shouldFail'); +const time = require('../helpers/time'); +const { ethGetBlock } = require('../helpers/web3'); +const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; diff --git a/test/library/Math.test.js b/test/math/Math.test.js similarity index 100% rename from test/library/Math.test.js rename to test/math/Math.test.js From 88f48be2873703fed1fb250f729defb94838f017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 17:00:12 -0300 Subject: [PATCH 123/205] Removed default value assignments. (#1432) (cherry picked from commit cfef58361f8c79daf684f084d04faac6e294dba2) --- contracts/drafts/ERC1046/TokenMetadata.sol | 2 +- contracts/payment/SplitPayment.sol | 2 -- contracts/utils/ReentrancyGuard.sol | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index 85b6ec671..9057711d9 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -13,7 +13,7 @@ contract ERC20TokenMetadata is IERC20 { } contract ERC20WithMetadata is ERC20TokenMetadata { - string private _tokenURI = ""; + string private _tokenURI; constructor(string tokenURI) public diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/SplitPayment.sol index 9c716e7ad..960772182 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/SplitPayment.sol @@ -24,8 +24,6 @@ contract SplitPayment { require(payees.length == shares.length); require(payees.length > 0); - _totalShares = 0; - _totalReleased = 0; for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares[i]); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 689c97205..4c10dc775 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -12,6 +12,8 @@ contract ReentrancyGuard { uint256 private _guardCounter; constructor() public { + // The counter starts at one to prevent changing it from zero to a non-zero + // value, which is a more expensive operation. _guardCounter = 1; } From c5a8680a9c7691c8e1045c0e6af235f90ef65d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 17:22:25 -0300 Subject: [PATCH 124/205] Moved Escrows into an escrow subdirectory, improved docs. (#1430) * Moved Escrows into an escrow subdirectory, improved docs. * Fixed escrow mock. * Fixed some more imports. (cherry picked from commit f3df2dab3d28b14242dbffd98f10c8181ed7dfd7) --- .../distribution/RefundableCrowdsale.sol | 2 +- contracts/mocks/ConditionalEscrowMock.sol | 2 +- contracts/payment/PullPayment.sol | 2 +- .../{ => escrow}/ConditionalEscrow.sol | 1 + contracts/payment/{ => escrow}/Escrow.sol | 19 ++++++++++++------- .../payment/{ => escrow}/RefundEscrow.sol | 11 ++++++++--- .../{ => escrow}/ConditionalEscrow.test.js | 4 ++-- test/payment/{ => escrow}/Escrow.behavior.js | 8 ++++---- test/payment/{ => escrow}/Escrow.test.js | 0 .../payment/{ => escrow}/RefundEscrow.test.js | 10 +++++----- 10 files changed, 35 insertions(+), 24 deletions(-) rename contracts/payment/{ => escrow}/ConditionalEscrow.sol (88%) rename contracts/payment/{ => escrow}/Escrow.sol (60%) rename contracts/payment/{ => escrow}/RefundEscrow.sol (81%) rename test/payment/{ => escrow}/ConditionalEscrow.test.js (91%) rename test/payment/{ => escrow}/Escrow.behavior.js (93%) rename test/payment/{ => escrow}/Escrow.test.js (100%) rename test/payment/{ => escrow}/RefundEscrow.test.js (94%) diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index a69d4a0ed..d55a573fb 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "../../math/SafeMath.sol"; import "./FinalizableCrowdsale.sol"; -import "../../payment/RefundEscrow.sol"; +import "../../payment/escrow/RefundEscrow.sol"; /** * @title RefundableCrowdsale diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 93a594b97..3e30c21a2 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../payment/ConditionalEscrow.sol"; +import "../payment/escrow/ConditionalEscrow.sol"; // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 67ef8c667..4db11c089 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./Escrow.sol"; +import "./escrow/Escrow.sol"; /** * @title PullPayment diff --git a/contracts/payment/ConditionalEscrow.sol b/contracts/payment/escrow/ConditionalEscrow.sol similarity index 88% rename from contracts/payment/ConditionalEscrow.sol rename to contracts/payment/escrow/ConditionalEscrow.sol index 645dad479..c3f63ee37 100644 --- a/contracts/payment/ConditionalEscrow.sol +++ b/contracts/payment/escrow/ConditionalEscrow.sol @@ -5,6 +5,7 @@ import "./Escrow.sol"; /** * @title ConditionalEscrow * @dev Base abstract escrow to only allow withdrawal if a condition is met. + * @dev Intended usage: See Escrow.sol. Same usage guidelines apply here. */ contract ConditionalEscrow is Escrow { /** diff --git a/contracts/payment/Escrow.sol b/contracts/payment/escrow/Escrow.sol similarity index 60% rename from contracts/payment/Escrow.sol rename to contracts/payment/escrow/Escrow.sol index 7fb118e3a..b2f2a85ee 100644 --- a/contracts/payment/Escrow.sol +++ b/contracts/payment/escrow/Escrow.sol @@ -1,14 +1,19 @@ pragma solidity ^0.4.24; -import "../math/SafeMath.sol"; -import "../ownership/Secondary.sol"; +import "../../math/SafeMath.sol"; +import "../../ownership/Secondary.sol"; -/** + /** * @title Escrow - * @dev Base escrow contract, holds funds destinated to a payee until they - * withdraw them. The contract that uses the escrow as its payment method - * should be its primary, and provide public methods redirecting to the escrow's - * deposit and withdraw. + * @dev Base escrow contract, holds funds designated for a payee until they + * withdraw them. + * @dev Intended usage: This contract (and derived escrow contracts) should be a + * standalone contract, that only interacts with the contract that instantiated + * it. That way, it is guaranteed that all Ether will be handled according to + * the Escrow rules, and there is no need to check for payable functions or + * transfers in the inheritance tree. The contract that uses the escrow as its + * payment method should be its primary, and provide public methods redirecting + * to the escrow's deposit and withdraw. */ contract Escrow is Secondary { using SafeMath for uint256; diff --git a/contracts/payment/RefundEscrow.sol b/contracts/payment/escrow/RefundEscrow.sol similarity index 81% rename from contracts/payment/RefundEscrow.sol rename to contracts/payment/escrow/RefundEscrow.sol index 3dfb3b965..a776a81c8 100644 --- a/contracts/payment/RefundEscrow.sol +++ b/contracts/payment/escrow/RefundEscrow.sol @@ -4,9 +4,14 @@ import "./ConditionalEscrow.sol"; /** * @title RefundEscrow - * @dev Escrow that holds funds for a beneficiary, deposited from multiple parties. - * The primary account may close the deposit period, and allow for either withdrawal - * by the beneficiary, or refunds to the depositors. + * @dev Escrow that holds funds for a beneficiary, deposited from multiple + * parties. + * @dev Intended usage: See Escrow.sol. Same usage guidelines apply here. + * @dev The primary account (that is, the contract that instantiates this + * contract) may deposit, close the deposit period, and allow for either + * withdrawal by the beneficiary, or refunds to the depositors. All interactions + * with RefundEscrow will be made through the primary contract. See the + * RefundableCrowdsale contract for an example of RefundEscrow’s use. */ contract RefundEscrow is ConditionalEscrow { enum State { Active, Refunding, Closed } diff --git a/test/payment/ConditionalEscrow.test.js b/test/payment/escrow/ConditionalEscrow.test.js similarity index 91% rename from test/payment/ConditionalEscrow.test.js rename to test/payment/escrow/ConditionalEscrow.test.js index bfb38dd86..c30b7bde5 100644 --- a/test/payment/ConditionalEscrow.test.js +++ b/test/payment/escrow/ConditionalEscrow.test.js @@ -1,7 +1,7 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); -const shouldFail = require('../helpers/shouldFail'); -const { ether } = require('../helpers/ether'); +const shouldFail = require('../../helpers/shouldFail'); +const { ether } = require('../../helpers/ether'); const BigNumber = web3.BigNumber; diff --git a/test/payment/Escrow.behavior.js b/test/payment/escrow/Escrow.behavior.js similarity index 93% rename from test/payment/Escrow.behavior.js rename to test/payment/escrow/Escrow.behavior.js index c724c5395..d7a7975e7 100644 --- a/test/payment/Escrow.behavior.js +++ b/test/payment/escrow/Escrow.behavior.js @@ -1,7 +1,7 @@ -const expectEvent = require('../helpers/expectEvent'); -const shouldFail = require('../helpers/shouldFail'); -const { ethGetBalance } = require('../helpers/web3'); -const { ether } = require('../helpers/ether'); +const expectEvent = require('../../helpers/expectEvent'); +const shouldFail = require('../../helpers/shouldFail'); +const { ethGetBalance } = require('../../helpers/web3'); +const { ether } = require('../../helpers/ether'); const BigNumber = web3.BigNumber; diff --git a/test/payment/Escrow.test.js b/test/payment/escrow/Escrow.test.js similarity index 100% rename from test/payment/Escrow.test.js rename to test/payment/escrow/Escrow.test.js diff --git a/test/payment/RefundEscrow.test.js b/test/payment/escrow/RefundEscrow.test.js similarity index 94% rename from test/payment/RefundEscrow.test.js rename to test/payment/escrow/RefundEscrow.test.js index 02a58a3b5..1f92e23af 100644 --- a/test/payment/RefundEscrow.test.js +++ b/test/payment/escrow/RefundEscrow.test.js @@ -1,8 +1,8 @@ -const shouldFail = require('../helpers/shouldFail'); -const expectEvent = require('../helpers/expectEvent'); -const { ethGetBalance } = require('../helpers/web3'); -const { ether } = require('../helpers/ether'); -const { ZERO_ADDRESS } = require('../helpers/constants'); +const shouldFail = require('../../helpers/shouldFail'); +const expectEvent = require('../../helpers/expectEvent'); +const { ethGetBalance } = require('../../helpers/web3'); +const { ether } = require('../../helpers/ether'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; From 3b34436b44cfb8d0fce95c862130d63fd993a3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 17 Oct 2018 18:18:41 -0300 Subject: [PATCH 125/205] Made some TokenVesting public functions private. (#1427) * Made some TokenVesting public functions private. * Fixed linter error. (cherry picked from commit df3c1137119892afde07df98a2157ba24c565589) --- contracts/drafts/TokenVesting.sol | 10 +++++----- test/drafts/TokenVesting.test.js | 15 +++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index b97b60b2b..965ace102 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -114,7 +114,7 @@ contract TokenVesting is Ownable { * @param token ERC20 token which is being vested */ function release(IERC20 token) public { - uint256 unreleased = releasableAmount(token); + uint256 unreleased = _releasableAmount(token); require(unreleased > 0); @@ -136,7 +136,7 @@ contract TokenVesting is Ownable { uint256 balance = token.balanceOf(address(this)); - uint256 unreleased = releasableAmount(token); + uint256 unreleased = _releasableAmount(token); uint256 refund = balance.sub(unreleased); _revoked[token] = true; @@ -150,15 +150,15 @@ 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 releasableAmount(IERC20 token) public view returns (uint256) { - return vestedAmount(token).sub(_released[token]); + function _releasableAmount(IERC20 token) private view 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(IERC20 token) public view returns (uint256) { + function _vestedAmount(IERC20 token) private view returns (uint256) { uint256 currentBalance = token.balanceOf(this); uint256 totalBalance = currentBalance.add(_released[token]); diff --git a/test/drafts/TokenVesting.test.js b/test/drafts/TokenVesting.test.js index 37864fbca..c43a0d8b8 100644 --- a/test/drafts/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -115,7 +115,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('should return the non-vested tokens when revoked by owner', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - const vested = await this.vesting.vestedAmount(this.token.address); + const vested = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); await this.vesting.revoke(this.token.address, { from: owner }); @@ -125,23 +125,22 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('should keep the vested tokens when revoked by owner', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - const vestedPre = await this.vesting.vestedAmount(this.token.address); + const vestedPre = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); await this.vesting.revoke(this.token.address, { from: owner }); - const vestedPost = await this.vesting.vestedAmount(this.token.address); + const vestedPost = vestedAmount(amount, await time.latest(), this.start, this.cliffDuration, this.duration); vestedPre.should.bignumber.equal(vestedPost); }); it('should fail to be revoked a second time', async function () { - await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(12)); - - await this.vesting.vestedAmount(this.token.address); - await this.vesting.revoke(this.token.address, { from: owner }); - await shouldFail.reverting(this.vesting.revoke(this.token.address, { from: owner })); }); + + function vestedAmount (total, now, start, cliffDuration, duration) { + return (now < start + cliffDuration) ? 0 : Math.round(total * (now - start) / duration); + } }); }); From 422b42bb6a788cbf3916483367b185e815dd2184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:47:35 -0300 Subject: [PATCH 126/205] Made some inherit-only contracts internal. (#1433) * Made some inherit-only contracts internal. * Added OwnableMock. (cherry picked from commit 96d6103e0b70c5a09005bc77cf5bb9310fb90ac3) --- contracts/access/roles/CapperRole.sol | 2 +- contracts/access/roles/MinterRole.sol | 2 +- contracts/access/roles/PauserRole.sol | 2 +- contracts/access/roles/SignerRole.sol | 2 +- contracts/drafts/SignatureBouncer.sol | 2 ++ contracts/introspection/ERC165.sol | 2 +- contracts/lifecycle/Pausable.sol | 2 +- contracts/mocks/OwnableMock.sol | 6 ++++++ contracts/ownership/Ownable.sol | 2 +- contracts/ownership/Secondary.sol | 2 +- contracts/payment/PullPayment.sol | 2 +- contracts/utils/ReentrancyGuard.sol | 2 +- test/ownership/Ownable.test.js | 2 +- 13 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 contracts/mocks/OwnableMock.sol diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index a79e8e694..d6b2ba066 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -10,7 +10,7 @@ contract CapperRole { Roles.Role private cappers; - constructor() public { + constructor() internal { _addCapper(msg.sender); } diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index d908e3004..57f4a5a80 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -10,7 +10,7 @@ contract MinterRole { Roles.Role private minters; - constructor() public { + constructor() internal { _addMinter(msg.sender); } diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index d59839d6b..58bb6a313 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -10,7 +10,7 @@ contract PauserRole { Roles.Role private pausers; - constructor() public { + constructor() internal { _addPauser(msg.sender); } diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index bbf8fd36f..6a2bc602d 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -10,7 +10,7 @@ contract SignerRole { Roles.Role private signers; - constructor() public { + constructor() internal { _addSigner(msg.sender); } diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index ff596b006..4327a2bbe 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -36,6 +36,8 @@ contract SignatureBouncer is SignerRole { // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes uint256 private constant _SIGNATURE_SIZE = 96; + constructor() internal {} + /** * @dev requires that a valid signature of a signer was provided */ diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 60bcd53f3..5d083acdf 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -25,7 +25,7 @@ contract ERC165 is IERC165 { * implement ERC165 itself */ constructor() - public + internal { _registerInterface(_InterfaceId_ERC165); } diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index a6cae2a55..0e7feb780 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -12,7 +12,7 @@ contract Pausable is PauserRole { bool private _paused; - constructor() public { + constructor() internal { _paused = false; } diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol new file mode 100644 index 000000000..e16a89012 --- /dev/null +++ b/contracts/mocks/OwnableMock.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.4.24; + +import "../ownership/Ownable.sol"; + +contract OwnableMock is Ownable { +} diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 5279d5d42..7b5b72102 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -17,7 +17,7 @@ contract Ownable { * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ - constructor() public { + constructor() internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index d602d67ec..02d2982a3 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -10,7 +10,7 @@ contract Secondary { /** * @dev Sets the primary account to the one that is creating the Secondary contract. */ - constructor() public { + constructor() internal { _primary = msg.sender; } diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 4db11c089..f6d7e2c1e 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -10,7 +10,7 @@ import "./escrow/Escrow.sol"; contract PullPayment { Escrow private _escrow; - constructor() public { + constructor() internal { _escrow = new Escrow(); } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 4c10dc775..368f2720f 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -11,7 +11,7 @@ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; - constructor() public { + constructor() internal { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; diff --git a/test/ownership/Ownable.test.js b/test/ownership/Ownable.test.js index 9b9c1bf3e..6f8a813e5 100644 --- a/test/ownership/Ownable.test.js +++ b/test/ownership/Ownable.test.js @@ -1,6 +1,6 @@ const { shouldBehaveLikeOwnable } = require('./Ownable.behavior'); -const Ownable = artifacts.require('Ownable'); +const Ownable = artifacts.require('OwnableMock'); contract('Ownable', function ([_, owner, ...otherAccounts]) { beforeEach(async function () { From 439410766065dc2322a555f6ee46d983329e4ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:47:55 -0300 Subject: [PATCH 127/205] Added replay attack notice to SignatureBouncer. (#1434) (cherry picked from commit ff0c048ad9fb24b1cb36fe43a0aae9010a87de77) --- contracts/drafts/SignatureBouncer.sol | 37 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index 4327a2bbe..2cd600b35 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -6,26 +6,33 @@ import "../cryptography/ECDSA.sol"; /** * @title SignatureBouncer * @author PhABC, Shrugs and aflesher - * @dev SignatureBouncer allows users to submit a signature as a permission to do an action. - * If the signature is from one of the authorized signer addresses, the signature - * is valid. + * @dev SignatureBouncer allows users to submit a signature as a permission to + * do an action. + * If the signature is from one of the authorized signer addresses, the + * signature is valid. + * Note that SignatureBouncer offers no protection against replay attacks, users + * must add this themselves! + * * Signer addresses can be individual servers signing grants or different - * users within a decentralized club that have permission to invite other members. - * This technique is useful for whitelists and airdrops; instead of putting all - * valid addresses on-chain, simply sign a grant of the form - * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid signer address. + * users within a decentralized club that have permission to invite other + * members. This technique is useful for whitelists and airdrops; instead of + * putting all valid addresses on-chain, simply sign a grant of the form + * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a + * valid signer address. * Then restrict access to your crowdsale/whitelist/airdrop using the * `onlyValidSignature` modifier (or implement your own using _isValidSignature). * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and - * `onlyValidSignatureAndData` can be used to restrict access to only a given method - * or a given method with given parameters respectively. + * `onlyValidSignatureAndData` can be used to restrict access to only a given + * method or a given method with given parameters respectively. * See the tests in SignatureBouncer.test.js for specific usage examples. - * @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _signature - * parameter the "last" parameter. You cannot sign a message that has its own - * signature in it so the last 128 bytes of msg.data (which represents the - * length of the _signature data and the _signaature data itself) is ignored when validating. - * Also non fixed sized parameters make constructing the data in the signature - * much more complex. See https://ethereum.stackexchange.com/a/50616 for more details. + * + * @notice A method that uses the `onlyValidSignatureAndData` modifier must make + * the _signature parameter the "last" parameter. You cannot sign a message that + * has its own signature in it so the last 128 bytes of msg.data (which + * represents the length of the _signature data and the _signaature data itself) + * is ignored when validating. Also non fixed sized parameters make constructing + * the data in the signature much more complex. + * See https://ethereum.stackexchange.com/a/50616 for more details. */ contract SignatureBouncer is SignerRole { using ECDSA for bytes32; From ab932e1873c87796188fdadee9aad8fa48ed5bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 10:49:01 -0300 Subject: [PATCH 128/205] Added leading underscore to internal functions, renamed supportsInterfaces. (#1435) (cherry picked from commit 0231fac51482b874621169351b9adaec51bd7ac3) --- contracts/introspection/ERC165Checker.sol | 24 +++++++++---------- contracts/mocks/ERC165CheckerMock.sol | 8 +++---- test/introspection/ERC165Checker.test.js | 28 +++++++++++------------ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 3491df904..2490b191e 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -20,15 +20,15 @@ library ERC165Checker { * @param account The address of the contract to query for support of ERC165 * @return true if the contract at account implements ERC165 */ - function supportsERC165(address account) + function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return supportsERC165Interface(account, _InterfaceId_ERC165) && - !supportsERC165Interface(account, _InterfaceId_Invalid); + return _supportsERC165Interface(account, _InterfaceId_ERC165) && + !_supportsERC165Interface(account, _InterfaceId_Invalid); } /** @@ -39,14 +39,14 @@ library ERC165Checker { * identifier interfaceId, false otherwise * @dev Interface identification is specified in ERC-165. */ - function supportsInterface(address account, bytes4 interfaceId) + function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId - return supportsERC165(account) && - supportsERC165Interface(account, interfaceId); + return _supportsERC165(account) && + _supportsERC165Interface(account, interfaceId); } /** @@ -57,19 +57,19 @@ library ERC165Checker { * interfaceIds list, false otherwise * @dev Interface identification is specified in ERC-165. */ - function supportsInterfaces(address account, bytes4[] interfaceIds) + function _supportsAllInterfaces(address account, bytes4[] interfaceIds) internal view returns (bool) { // query support of ERC165 itself - if (!supportsERC165(account)) { + if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { - if (!supportsERC165Interface(account, interfaceIds[i])) { + if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } @@ -89,14 +89,14 @@ library ERC165Checker { * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ - function supportsERC165Interface(address account, bytes4 interfaceId) + function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId - (bool success, bool result) = callERC165SupportsInterface( + (bool success, bool result) = _callERC165SupportsInterface( account, interfaceId); return (success && result); @@ -110,7 +110,7 @@ library ERC165Checker { * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ - function callERC165SupportsInterface( + function _callERC165SupportsInterface( address account, bytes4 interfaceId ) diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index b0728ba15..559cea0d7 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -10,7 +10,7 @@ contract ERC165CheckerMock { view returns (bool) { - return account.supportsERC165(); + return account._supportsERC165(); } function supportsInterface(address account, bytes4 interfaceId) @@ -18,14 +18,14 @@ contract ERC165CheckerMock { view returns (bool) { - return account.supportsInterface(interfaceId); + return account._supportsInterface(interfaceId); } - function supportsInterfaces(address account, bytes4[] interfaceIds) + function supportsAllInterfaces(address account, bytes4[] interfaceIds) public view returns (bool) { - return account.supportsInterfaces(interfaceIds); + return account._supportsAllInterfaces(interfaceIds); } } diff --git a/test/introspection/ERC165Checker.test.js b/test/introspection/ERC165Checker.test.js index a6bfc518d..7f5dc9fc5 100644 --- a/test/introspection/ERC165Checker.test.js +++ b/test/introspection/ERC165Checker.test.js @@ -32,8 +32,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(false); }); }); @@ -53,8 +53,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(false); }); }); @@ -74,8 +74,8 @@ contract('ERC165Checker', function () { supported.should.equal(true); }); - it('supports mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, [DUMMY_ID]); + it('supports mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]); supported.should.equal(true); }); }); @@ -98,22 +98,22 @@ contract('ERC165Checker', function () { }; }); - it('supports all interfaceIds via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(this.target.address, this.supportedInterfaces); + it('supports all interfaceIds via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(this.target.address, this.supportedInterfaces); supported.should.equal(true); }); - it('supports none of the interfaces queried via supportsInterfaces', async function () { + it('supports none of the interfaces queried via supportsAllInterfaces', async function () { const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2]; - const supported = await this.mock.supportsInterfaces(this.target.address, interfaceIdsToTest); + const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest); supported.should.equal(false); }); - it('supports not all of the interfaces queried via supportsInterfaces', async function () { + it('supports not all of the interfaces queried via supportsAllInterfaces', async function () { const interfaceIdsToTest = [...this.supportedInterfaces, DUMMY_UNSUPPORTED_ID]; - const supported = await this.mock.supportsInterfaces(this.target.address, interfaceIdsToTest); + const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest); supported.should.equal(false); }); }); @@ -129,8 +129,8 @@ contract('ERC165Checker', function () { supported.should.equal(false); }); - it('does not support mock interface via supportsInterfaces', async function () { - const supported = await this.mock.supportsInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]); + it('does not support mock interface via supportsAllInterfaces', async function () { + const supported = await this.mock.supportsAllInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]); supported.should.equal(false); }); }); From c126e3e81a317e2a3c9dcf99279cb862e2500115 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 18 Oct 2018 19:30:33 +0530 Subject: [PATCH 129/205] Events added to Secondary (#1425) * Update contracts/ownership/Secondary.sol * Update Secondary.sol * Update Secondary.test.js * Update Secondary.test.js * Update Secondary.sol (cherry picked from commit cbe414864fc74290ae1c08175a4b1f7b59941bbc) --- contracts/ownership/Secondary.sol | 16 ++++++++++++++-- test/ownership/Secondary.test.js | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index 02d2982a3..67d2250d5 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -7,11 +7,16 @@ pragma solidity ^0.4.24; contract Secondary { address private _primary; + event PrimaryTransferred( + address recipient + ); + /** * @dev Sets the primary account to the one that is creating the Secondary contract. */ constructor() internal { _primary = msg.sender; + emit PrimaryTransferred(_primary); } /** @@ -22,13 +27,20 @@ contract Secondary { _; } + /** + * @return the address of the primary. + */ function primary() public view returns (address) { return _primary; } - + + /** + * @dev Transfers contract to a new primary. + * @param recipient The address of new primary. + */ function transferPrimary(address recipient) public onlyPrimary { require(recipient != address(0)); - _primary = recipient; + emit PrimaryTransferred(_primary); } } diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index 55283963b..c8772db1f 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -1,4 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); +const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); const SecondaryMock = artifacts.require('SecondaryMock'); @@ -27,7 +28,8 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) { describe('transferPrimary', function () { it('makes the recipient the new primary', async function () { - await this.secondary.transferPrimary(newPrimary, { from: primary }); + const { logs } = await this.secondary.transferPrimary(newPrimary, { from: primary }); + expectEvent.inLogs(logs, 'PrimaryTransferred', { recipient: newPrimary }); (await this.secondary.primary()).should.equal(newPrimary); }); From 5f3ecd9c64cc9051cff97e6c92452eda6cec44fa Mon Sep 17 00:00:00 2001 From: Christopher Glisch Date: Thu, 18 Oct 2018 10:26:39 -0400 Subject: [PATCH 130/205] Added address of pauser/unpauser in events (#1410) * Added address of pauser/unpauser in events * Added the account to the Pausable tests. (cherry picked from commit fcab9c89f25376227399914a6e4b8e89ee3b21d3) --- contracts/lifecycle/Pausable.sol | 8 ++++---- test/lifecycle/Pausable.test.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 0e7feb780..3703fed4b 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -7,8 +7,8 @@ import "../access/roles/PauserRole.sol"; * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is PauserRole { - event Paused(); - event Unpaused(); + event Paused(address account); + event Unpaused(address account); bool private _paused; @@ -44,7 +44,7 @@ contract Pausable is PauserRole { */ function pause() public onlyPauser whenNotPaused { _paused = true; - emit Paused(); + emit Paused(msg.sender); } /** @@ -52,6 +52,6 @@ contract Pausable is PauserRole { */ function unpause() public onlyPauser whenPaused { _paused = false; - emit Unpaused(); + emit Unpaused(msg.sender); } } diff --git a/test/lifecycle/Pausable.test.js b/test/lifecycle/Pausable.test.js index a7f6d637d..f279e09a7 100644 --- a/test/lifecycle/Pausable.test.js +++ b/test/lifecycle/Pausable.test.js @@ -57,7 +57,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('emits a Paused event', function () { - expectEvent.inLogs(this.logs, 'Paused'); + expectEvent.inLogs(this.logs, 'Paused', { account: pauser }); }); it('cannot perform normal process in pause', async function () { @@ -89,7 +89,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts }); it('emits an Unpaused event', function () { - expectEvent.inLogs(this.logs, 'Unpaused'); + expectEvent.inLogs(this.logs, 'Unpaused', { account: pauser }); }); it('should resume allowing normal process', async function () { From 6db4f0bc8f2eacbcf4e4890b9419946be6b568c9 Mon Sep 17 00:00:00 2001 From: cardmaniac992 <44122792+cardmaniac992@users.noreply.github.com> Date: Thu, 18 Oct 2018 16:26:54 +0200 Subject: [PATCH 131/205] SplitPayment improvements (#1417) * Renamed file, added events and set _addPayee to private * unwanted file * adjusted test * adjusted test * PaymentReceived event added * Added event testing. * Fix static tests (cherry picked from commit a07499796af0a00bf12283f5591f934843a1fbc2) --- .../{SplitPayment.sol => PaymentSplitter.sol} | 16 ++++++++--- ...ayment.test.js => PaymentSplitter.test.js} | 28 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) rename contracts/payment/{SplitPayment.sol => PaymentSplitter.sol} (84%) rename test/payment/{SplitPayment.test.js => PaymentSplitter.test.js} (73%) diff --git a/contracts/payment/SplitPayment.sol b/contracts/payment/PaymentSplitter.sol similarity index 84% rename from contracts/payment/SplitPayment.sol rename to contracts/payment/PaymentSplitter.sol index 960772182..0a1b470ef 100644 --- a/contracts/payment/SplitPayment.sol +++ b/contracts/payment/PaymentSplitter.sol @@ -3,13 +3,17 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; /** - * @title SplitPayment + * @title PaymentSplitter * @dev This contract can be used when payments need to be received by a group * of people and split proportionately to some number of shares they own. */ -contract SplitPayment { +contract PaymentSplitter { using SafeMath for uint256; + event PayeeAdded(address account, uint256 shares); + event PaymentReleased(address to, uint256 amount); + event PaymentReceived(address from, uint256 amount); + uint256 private _totalShares; uint256 private _totalReleased; @@ -32,7 +36,9 @@ contract SplitPayment { /** * @dev payable fallback */ - function () external payable {} + function () external payable { + emit PaymentReceived(msg.sender, msg.value); + } /** * @return the total shares of the contract. @@ -89,6 +95,7 @@ contract SplitPayment { _totalReleased = _totalReleased.add(payment); account.transfer(payment); + emit PaymentReleased(account, payment); } /** @@ -96,7 +103,7 @@ contract SplitPayment { * @param account The address of the payee to add. * @param shares_ The number of shares owned by the payee. */ - function _addPayee(address account, uint256 shares_) internal { + function _addPayee(address account, uint256 shares_) private { require(account != address(0)); require(shares_ > 0); require(_shares[account] == 0); @@ -104,5 +111,6 @@ contract SplitPayment { _payees.push(account); _shares[account] = shares_; _totalShares = _totalShares.add(shares_); + emit PayeeAdded(account, shares_); } } diff --git a/test/payment/SplitPayment.test.js b/test/payment/PaymentSplitter.test.js similarity index 73% rename from test/payment/SplitPayment.test.js rename to test/payment/PaymentSplitter.test.js index 6a10a5131..60e5654dc 100644 --- a/test/payment/SplitPayment.test.js +++ b/test/payment/PaymentSplitter.test.js @@ -1,4 +1,5 @@ const { ethGetBalance } = require('../helpers/web3'); +const expectEvent = require('../helpers/expectEvent'); const { sendEther } = require('./../helpers/sendTransaction'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('./../helpers/constants'); @@ -10,33 +11,33 @@ require('chai') .should(); const shouldFail = require('../helpers/shouldFail'); -const SplitPayment = artifacts.require('SplitPayment'); +const PaymentSplitter = artifacts.require('PaymentSplitter'); -contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { +contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpayee1, payer1]) { const amount = ether(1.0); it('rejects an empty set of payees', async function () { - await shouldFail.reverting(SplitPayment.new([], [])); + await shouldFail.reverting(PaymentSplitter.new([], [])); }); it('rejects more payees than shares', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2, payee3], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2, payee3], [20, 30])); }); it('rejects more shares than payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 30, 40])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 30, 40])); }); it('rejects null payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, ZERO_ADDRESS], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, ZERO_ADDRESS], [20, 30])); }); it('rejects zero-valued shares', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee2], [20, 0])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee2], [20, 0])); }); it('rejects repeated payees', async function () { - await shouldFail.reverting(SplitPayment.new([payee1, payee1], [20, 30])); + await shouldFail.reverting(PaymentSplitter.new([payee1, payee1], [20, 30])); }); context('once deployed', function () { @@ -44,7 +45,7 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, this.payees = [payee1, payee2, payee3]; this.shares = [20, 10, 70]; - this.contract = await SplitPayment.new(this.payees, this.shares); + this.contract = await PaymentSplitter.new(this.payees, this.shares); }); it('should have total shares', async function () { @@ -90,19 +91,22 @@ contract('SplitPayment', function ([_, owner, payee1, payee2, payee3, nonpayee1, // distribute to payees const initAmount1 = await ethGetBalance(payee1); - await this.contract.release(payee1); + const { logs: logs1 } = await this.contract.release(payee1); const profit1 = (await ethGetBalance(payee1)).sub(initAmount1); profit1.sub(web3.toWei(0.20, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs1, 'PaymentReleased', { to: payee1, amount: profit1 }); const initAmount2 = await ethGetBalance(payee2); - await this.contract.release(payee2); + const { logs: logs2 } = await this.contract.release(payee2); const profit2 = (await ethGetBalance(payee2)).sub(initAmount2); profit2.sub(web3.toWei(0.10, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs2, 'PaymentReleased', { to: payee2, amount: profit2 }); const initAmount3 = await ethGetBalance(payee3); - await this.contract.release(payee3); + const { logs: logs3 } = await this.contract.release(payee3); const profit3 = (await ethGetBalance(payee3)).sub(initAmount3); profit3.sub(web3.toWei(0.70, 'ether')).abs().should.be.bignumber.lt(1e16); + expectEvent.inLogs(logs3, 'PaymentReleased', { to: payee3, amount: profit3 }); // end balance should be zero (await ethGetBalance(this.contract.address)).should.be.bignumber.equal(0); From 4115686b4f8c1abf29f1f855eb15308076159959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 11:27:46 -0300 Subject: [PATCH 132/205] TokenVesting improvements (#1431) * Improved TokenVesting events. * Added extra checks to TokenVesting. * Renamed the events. * Fixed linter error. * Fixed a test that failed to cover a require. * Renamed TokensRevoked to TokenVestingRevoked. (cherry picked from commit 67dac7ae9960fd1790671a315cde56c901db5271) --- contracts/drafts/TokenVesting.sol | 10 ++++++---- test/drafts/TokenVesting.test.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 965ace102..2f5fd2fdc 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -16,8 +16,8 @@ contract TokenVesting is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; - event Released(uint256 amount); - event Revoked(); + event TokensReleased(address token, uint256 amount); + event TokenVestingRevoked(address token); // beneficiary of tokens after they are released address private _beneficiary; @@ -52,6 +52,8 @@ contract TokenVesting is Ownable { { require(beneficiary != address(0)); require(cliffDuration <= duration); + require(duration > 0); + require(start.add(duration) > block.timestamp); _beneficiary = beneficiary; _revocable = revocable; @@ -122,7 +124,7 @@ contract TokenVesting is Ownable { token.safeTransfer(_beneficiary, unreleased); - emit Released(unreleased); + emit TokensReleased(token, unreleased); } /** @@ -143,7 +145,7 @@ contract TokenVesting is Ownable { token.safeTransfer(owner(), refund); - emit Revoked(); + emit TokenVestingRevoked(token); } /** diff --git a/test/drafts/TokenVesting.test.js b/test/drafts/TokenVesting.test.js index c43a0d8b8..be872ae22 100644 --- a/test/drafts/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -1,4 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); +const expectEvent = require('../helpers/expectEvent'); const time = require('../helpers/time'); const { ethGetBlock } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); @@ -22,7 +23,7 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { this.duration = time.duration.years(2); }); - it('rejects a duration shorter than the cliff', async function () { + it('reverts with a duration shorter than the cliff', async function () { const cliffDuration = this.duration; const duration = this.cliffDuration; @@ -33,12 +34,28 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { ); }); - it('requires a valid beneficiary', async function () { + it('reverts with a null beneficiary', async function () { await shouldFail.reverting( TokenVesting.new(ZERO_ADDRESS, this.start, this.cliffDuration, this.duration, true, { from: owner }) ); }); + it('reverts with a null duration', async function () { + // cliffDuration should also be 0, since the duration must be larger than the cliff + await shouldFail.reverting( + TokenVesting.new(beneficiary, this.start, 0, 0, true, { from: owner }) + ); + }); + + it('reverts if the end time is in the past', async function () { + const now = await time.latest(); + + this.start = now - this.duration - time.duration.minutes(1); + await shouldFail.reverting( + TokenVesting.new(beneficiary, this.start, this.cliffDuration, this.duration, true, { from: owner }) + ); + }); + context('once deployed', function () { beforeEach(async function () { this.vesting = await TokenVesting.new( @@ -62,7 +79,11 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { it('can be released after cliff', async function () { await time.increaseTo(this.start + this.cliffDuration + time.duration.weeks(1)); - await this.vesting.release(this.token.address); + const { logs } = await this.vesting.release(this.token.address); + expectEvent.inLogs(logs, 'TokensReleased', { + token: this.token.address, + amount: await this.token.balanceOf(beneficiary), + }); }); it('should release proper amount after cliff', async function () { @@ -100,7 +121,8 @@ contract('TokenVesting', function ([_, owner, beneficiary]) { }); it('should be revoked by owner if revocable is set', async function () { - await this.vesting.revoke(this.token.address, { from: owner }); + const { logs } = await this.vesting.revoke(this.token.address, { from: owner }); + expectEvent.inLogs(logs, 'TokenVestingRevoked', { token: this.token.address }); (await this.vesting.revoked(this.token.address)).should.equal(true); }); From 1b27b4bb34882a731528b16381639c3bc2a65864 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 18 Oct 2018 20:55:03 +0530 Subject: [PATCH 133/205] Improved SafeERC20 allowance handling (#1407) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * allowance methods in library * Improved SafeERC20 tests. * Fixed test coverage. (cherry picked from commit 315f426f5c2db7953b977bbf605b5d796636cd97) --- contracts/mocks/SafeERC20Helper.sol | 58 +++++++++++++------ contracts/token/ERC20/SafeERC20.sol | 29 ++++++++++ test/token/ERC20/SafeERC20.test.js | 90 ++++++++++++++++++++++++----- 3 files changed, 142 insertions(+), 35 deletions(-) diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index c80c762d9..7e639f86f 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -3,10 +3,8 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; -contract ERC20FailingMock is IERC20 { - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20FailingMock { + uint256 private _allowance; function transfer(address, uint256) public returns (bool) { return false; @@ -20,19 +18,13 @@ contract ERC20FailingMock is IERC20 { return false; } - function balanceOf(address) public view returns (uint256) { - return 0; - } - function allowance(address, address) public view returns (uint256) { return 0; } } -contract ERC20SucceedingMock is IERC20 { - function totalSupply() public view returns (uint256) { - return 0; - } +contract ERC20SucceedingMock { + uint256 private _allowance; function transfer(address, uint256) public returns (bool) { return true; @@ -46,12 +38,12 @@ contract ERC20SucceedingMock is IERC20 { return true; } - function balanceOf(address) public view returns (uint256) { - return 0; + function setAllowance(uint256 allowance_) public { + _allowance = allowance_; } function allowance(address, address) public view returns (uint256) { - return 0; + return _allowance; } } @@ -62,10 +54,12 @@ contract SafeERC20Helper { IERC20 private _succeeding; constructor() public { - _failing = new ERC20FailingMock(); - _succeeding = new ERC20SucceedingMock(); + _failing = IERC20(new ERC20FailingMock()); + _succeeding = IERC20(new ERC20SucceedingMock()); } + // Using _failing + function doFailingTransfer() public { _failing.safeTransfer(address(0), 0); } @@ -78,6 +72,16 @@ contract SafeERC20Helper { _failing.safeApprove(address(0), 0); } + function doFailingIncreaseAllowance() public { + _failing.safeIncreaseAllowance(address(0), 0); + } + + function doFailingDecreaseAllowance() public { + _failing.safeDecreaseAllowance(address(0), 0); + } + + // Using _succeeding + function doSucceedingTransfer() public { _succeeding.safeTransfer(address(0), 0); } @@ -86,7 +90,23 @@ contract SafeERC20Helper { _succeeding.safeTransferFrom(address(0), address(0), 0); } - function doSucceedingApprove() public { - _succeeding.safeApprove(address(0), 0); + function doSucceedingApprove(uint256 amount) public { + _succeeding.safeApprove(address(0), amount); + } + + function doSucceedingIncreaseAllowance(uint256 amount) public { + _succeeding.safeIncreaseAllowance(address(0), amount); + } + + function doSucceedingDecreaseAllowance(uint256 amount) public { + _succeeding.safeDecreaseAllowance(address(0), amount); + } + + function setAllowance(uint256 allowance_) public { + ERC20SucceedingMock(_succeeding).setAllowance(allowance_); + } + + function allowance() public view returns (uint256) { + return _succeeding.allowance(address(0), address(0)); } } diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 10c6ff2bc..9e6bf6a20 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -10,6 +10,9 @@ import "./IERC20.sol"; * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { + + using SafeMath for uint256; + function safeTransfer( IERC20 token, address to, @@ -38,6 +41,32 @@ library SafeERC20 { ) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require((value == 0) || (token.allowance(msg.sender, spender) == 0)); require(token.approve(spender, value)); } + + function safeIncreaseAllowance( + IERC20 token, + address spender, + uint256 value + ) + internal + { + uint256 newAllowance = token.allowance(address(this), spender).add(value); + require(token.approve(spender, newAllowance)); + } + + function safeDecreaseAllowance( + IERC20 token, + address spender, + uint256 value + ) + internal + { + uint256 newAllowance = token.allowance(address(this), spender).sub(value); + require(token.approve(spender, newAllowance)); + } } diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index b6c87554b..c8dea7382 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -10,27 +10,85 @@ contract('SafeERC20', function () { this.helper = await SafeERC20Helper.new(); }); - it('should throw on failed transfer', async function () { - await shouldFail.reverting(this.helper.doFailingTransfer()); + describe('with token that returns false on all calls', function () { + it('reverts on transfer', async function () { + await shouldFail.reverting(this.helper.doFailingTransfer()); + }); + + it('reverts on transferFrom', async function () { + await shouldFail.reverting(this.helper.doFailingTransferFrom()); + }); + + it('reverts on approve', async function () { + await shouldFail.reverting(this.helper.doFailingApprove()); + }); + + it('reverts on increaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingIncreaseAllowance()); + }); + + it('reverts on decreaseAllowance', async function () { + await shouldFail.reverting(this.helper.doFailingDecreaseAllowance()); + }); }); - it('should throw on failed transferFrom', async function () { - await shouldFail.reverting(this.helper.doFailingTransferFrom()); - }); + describe('with token that returns true on all calls', function () { + it('doesn\'t revert on transfer', async function () { + await this.helper.doSucceedingTransfer(); + }); - it('should throw on failed approve', async function () { - await shouldFail.reverting(this.helper.doFailingApprove()); - }); + it('doesn\'t revert on transferFrom', async function () { + await this.helper.doSucceedingTransferFrom(); + }); - it('should not throw on succeeding transfer', async function () { - await this.helper.doSucceedingTransfer(); - }); + describe('approvals', function () { + context('with zero allowance', function () { + beforeEach(async function () { + await this.helper.setAllowance(0); + }); - it('should not throw on succeeding transferFrom', async function () { - await this.helper.doSucceedingTransferFrom(); - }); + it('doesn\'t revert when approving a non-zero allowance', async function () { + await this.helper.doSucceedingApprove(100); + }); - it('should not throw on succeeding approve', async function () { - await this.helper.doSucceedingApprove(); + it('doesn\'t revert when approving a zero allowance', async function () { + await this.helper.doSucceedingApprove(0); + }); + + it('doesn\'t revert when increasing the allowance', async function () { + await this.helper.doSucceedingIncreaseAllowance(10); + }); + + it('reverts when decreasing the allowance', async function () { + await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(10)); + }); + }); + + context('with non-zero allowance', function () { + beforeEach(async function () { + await this.helper.setAllowance(100); + }); + + it('reverts when approving a non-zero allowance', async function () { + await shouldFail.reverting(this.helper.doSucceedingApprove(20)); + }); + + it('doesn\'t revert when approving a zero allowance', async function () { + await this.helper.doSucceedingApprove(0); + }); + + it('doesn\'t revert when increasing the allowance', async function () { + await this.helper.doSucceedingIncreaseAllowance(10); + }); + + it('doesn\'t revert when decreasing the allowance to a positive value', async function () { + await this.helper.doSucceedingDecreaseAllowance(50); + }); + + it('reverts when decreasing the allowance to a negative value', async function () { + await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(200)); + }); + }); + }); }); }); From 5ee55c4af307a03fb6804443e94d4dd5ee5c8e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:35:57 -0300 Subject: [PATCH 134/205] Internal crowdsales (#1439) * Made some internal crowdsale methods internal. * Made all Crowdsale constructors internal. (cherry picked from commit d9fdffe88e8474f5d0cd469d0c14714bf436f34e) --- contracts/crowdsale/Crowdsale.sol | 4 +++- .../crowdsale/distribution/FinalizableCrowdsale.sol | 2 +- .../crowdsale/distribution/PostDeliveryCrowdsale.sol | 2 ++ contracts/crowdsale/distribution/RefundableCrowdsale.sol | 2 +- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 2 +- contracts/crowdsale/emission/MintedCrowdsale.sol | 1 + contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 2 +- contracts/crowdsale/validation/CappedCrowdsale.sol | 3 ++- .../crowdsale/validation/IndividuallyCappedCrowdsale.sol | 3 +++ contracts/crowdsale/validation/TimedCrowdsale.sol | 3 ++- contracts/mocks/CrowdsaleMock.sol | 9 +++++++++ test/crowdsale/Crowdsale.test.js | 2 +- 12 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 contracts/mocks/CrowdsaleMock.sol diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index c1302ede4..f425718fd 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -57,7 +57,7 @@ contract Crowdsale { * @param wallet Address where collected funds will be forwarded to * @param token Address of the token being sold */ - constructor(uint256 rate, address wallet, IERC20 token) public { + constructor(uint256 rate, address wallet, IERC20 token) internal { require(rate > 0); require(wallet != address(0)); require(token != address(0)); @@ -152,6 +152,7 @@ contract Crowdsale { uint256 weiAmount ) internal + view { require(beneficiary != address(0)); require(weiAmount != 0); @@ -167,6 +168,7 @@ contract Crowdsale { uint256 weiAmount ) internal + view { // optional override } diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index a640dca83..bcdfa4563 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -15,7 +15,7 @@ contract FinalizableCrowdsale is TimedCrowdsale { event CrowdsaleFinalized(); - constructor() public { + constructor() internal { _finalized = false; } diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index da9392aed..ca05f6d66 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -13,6 +13,8 @@ contract PostDeliveryCrowdsale is TimedCrowdsale { mapping(address => uint256) private _balances; + constructor() internal {} + /** * @dev Withdraw tokens only after crowdsale ends. * @param beneficiary Whose tokens will be withdrawn. diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index d55a573fb..d670f9ced 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -22,7 +22,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale { * @dev Constructor, creates RefundEscrow. * @param goal Funding goal */ - constructor(uint256 goal) public { + constructor(uint256 goal) internal { require(goal > 0); _escrow = new RefundEscrow(wallet()); _goal = goal; diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index 736635e0b..ec9918feb 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -19,7 +19,7 @@ contract AllowanceCrowdsale is Crowdsale { * @dev Constructor, takes token wallet address. * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale */ - constructor(address tokenWallet) public { + constructor(address tokenWallet) internal { require(tokenWallet != address(0)); _tokenWallet = tokenWallet; } diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index 62b03189a..3ebea857d 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -9,6 +9,7 @@ import "../../token/ERC20/ERC20Mintable.sol"; * Token ownership should be transferred to MintedCrowdsale for minting. */ contract MintedCrowdsale is Crowdsale { + constructor() internal {} /** * @dev Overrides delivery by minting tokens upon purchase. diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 386c6202b..70189a168 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -20,7 +20,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { * @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale */ - constructor(uint256 initialRate, uint256 finalRate) public { + constructor(uint256 initialRate, uint256 finalRate) internal { require(finalRate > 0); require(initialRate >= finalRate); _initialRate = initialRate; diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 21708c34a..4d9eb604d 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -16,7 +16,7 @@ contract CappedCrowdsale is Crowdsale { * @dev Constructor, takes maximum amount of wei accepted in the crowdsale. * @param cap Max amount of wei to be contributed */ - constructor(uint256 cap) public { + constructor(uint256 cap) internal { require(cap > 0); _cap = cap; } @@ -46,6 +46,7 @@ contract CappedCrowdsale is Crowdsale { uint256 weiAmount ) internal + view { super._preValidatePurchase(beneficiary, weiAmount); require(weiRaised().add(weiAmount) <= _cap); diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index d00cb602e..5a5d4e317 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -14,6 +14,8 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { mapping(address => uint256) private _contributions; mapping(address => uint256) private _caps; + constructor() internal {} + /** * @dev Sets a specific beneficiary's maximum contribution. * @param beneficiary Address to be capped @@ -53,6 +55,7 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { uint256 weiAmount ) internal + view { super._preValidatePurchase(beneficiary, weiAmount); require( diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index 098112cae..d39242578 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -26,7 +26,7 @@ contract TimedCrowdsale is Crowdsale { * @param openingTime Crowdsale opening time * @param closingTime Crowdsale closing time */ - constructor(uint256 openingTime, uint256 closingTime) public { + constructor(uint256 openingTime, uint256 closingTime) internal { // solium-disable-next-line security/no-block-members require(openingTime >= block.timestamp); require(closingTime >= openingTime); @@ -77,6 +77,7 @@ contract TimedCrowdsale is Crowdsale { ) internal onlyWhileOpen + view { super._preValidatePurchase(beneficiary, weiAmount); } diff --git a/contracts/mocks/CrowdsaleMock.sol b/contracts/mocks/CrowdsaleMock.sol new file mode 100644 index 000000000..834105e6a --- /dev/null +++ b/contracts/mocks/CrowdsaleMock.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.24; + +import "../crowdsale/Crowdsale.sol"; + +contract CrowdsaleMock is Crowdsale { + constructor(uint256 rate, address wallet, IERC20 token) public + Crowdsale(rate, wallet, token) { + } +} diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index 8875e9157..b7528e4e9 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -10,7 +10,7 @@ require('chai') .use(require('chai-bignumber')(BigNumber)) .should(); -const Crowdsale = artifacts.require('Crowdsale'); +const Crowdsale = artifacts.require('CrowdsaleMock'); const SimpleToken = artifacts.require('SimpleToken'); contract('Crowdsale', function ([_, investor, wallet, purchaser]) { From 6e055019d4ab1815f928f13b0825689c856ab14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:36:11 -0300 Subject: [PATCH 135/205] Closing time must be strictly after opening time. (#1440) (cherry picked from commit 1c5f16ae2659c3c158baebff077cc414fd9c5991) --- contracts/crowdsale/validation/TimedCrowdsale.sol | 2 +- test/crowdsale/TimedCrowdsale.test.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index d39242578..73d6a5c0f 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -29,7 +29,7 @@ contract TimedCrowdsale is Crowdsale { constructor(uint256 openingTime, uint256 closingTime) internal { // solium-disable-next-line security/no-block-members require(openingTime >= block.timestamp); - require(closingTime >= openingTime); + require(closingTime > openingTime); _openingTime = openingTime; _closingTime = closingTime; diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index eb2a9bf51..5b0b457b7 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -29,18 +29,24 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { this.token = await SimpleToken.new(); }); - it('rejects an opening time in the past', async function () { + it('reverts if the opening time is in the past', async function () { await shouldFail.reverting(TimedCrowdsaleImpl.new( (await time.latest()) - time.duration.days(1), this.closingTime, rate, wallet, this.token.address )); }); - it('rejects a closing time before the opening time', async function () { + it('reverts if the closing time is before the opening time', async function () { await shouldFail.reverting(TimedCrowdsaleImpl.new( this.openingTime, this.openingTime - time.duration.seconds(1), rate, wallet, this.token.address )); }); + it('reverts if the closing time equals the opening time', async function () { + await shouldFail.reverting(TimedCrowdsaleImpl.new( + this.openingTime, this.openingTime, rate, wallet, this.token.address + )); + }); + context('with crowdsale', function () { beforeEach(async function () { this.crowdsale = await TimedCrowdsaleImpl.new( From 2e848e12d118a9975b8b79bb018d007c430c4f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:36:27 -0300 Subject: [PATCH 136/205] IncPriceCrowdsale consistently returns 0 outside of the crowdsale window. (#1442) (cherry picked from commit 9155bfe27f2ad2423e5ec5d4205cc42cc4aba566) --- contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 4 ++++ test/crowdsale/IncreasingPriceCrowdsale.test.js | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 70189a168..4d2b44931 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -47,6 +47,10 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { * @return The number of tokens a buyer gets per wei at a given time */ function getCurrentRate() public view returns (uint256) { + if (!isOpen()) { + return 0; + } + // solium-disable-next-line security/no-block-members uint256 elapsedTime = block.timestamp.sub(openingTime()); uint256 timeRange = closingTime().sub(openingTime()); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index a76186bbc..51946b5ee 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -59,6 +59,15 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) (await this.crowdsale.finalRate()).should.be.bignumber.equal(finalRate); }); + it('returns a rate of 0 before the crowdsale starts', async function () { + (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); + }); + + it('returns a rate of 0 after the crowdsale ends', async function () { + await time.increaseTo(this.afterClosingTime); + (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); + }); + it('at start', async function () { await time.increaseTo(this.startTime); await this.crowdsale.buyTokens(investor, { value, from: purchaser }); From 0ead40ae03be2ec9e01ecf52dcab754b12c9085f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:49:31 -0300 Subject: [PATCH 137/205] ERC20Capped now capps _all_ minting, even internal calls. (#1443) (cherry picked from commit c8220aeea8e194de2a9c8e8daaa574f5e1e033f9) --- contracts/token/ERC20/ERC20Capped.sol | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 9f3ea8bfc..a80dd491c 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -24,22 +24,8 @@ contract ERC20Capped is ERC20Mintable { return _cap; } - /** - * @dev Function to mint tokens - * @param to The address that will receive the minted tokens. - * @param value The amount of tokens to mint. - * @return A boolean that indicates if the operation was successful. - */ - function mint( - address to, - uint256 value - ) - public - returns (bool) - { + function _mint(address account, uint256 value) internal { require(totalSupply().add(value) <= _cap); - - return super.mint(to, value); + super._mint(account, value); } - } From e237530538d1cf1c53f19fdfee054a8f4e1079d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:49:46 -0300 Subject: [PATCH 138/205] Made tokenURI external, as per the spec. (#1444) (cherry picked from commit 5bf390786291c599601ce1c966971b20d4b6ca54) --- contracts/token/ERC721/ERC721Metadata.sol | 2 +- contracts/token/ERC721/IERC721Metadata.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 4fb35543c..bd1105188 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -54,7 +54,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ - function tokenURI(uint256 tokenId) public view returns (string) { + function tokenURI(uint256 tokenId) external view returns (string) { require(_exists(tokenId)); return _tokenURIs[tokenId]; } diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index 2e1521208..15b5ae4c6 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -9,5 +9,5 @@ import "./IERC721.sol"; contract IERC721Metadata is IERC721 { function name() external view returns (string); function symbol() external view returns (string); - function tokenURI(uint256 tokenId) public view returns (string); + function tokenURI(uint256 tokenId) external view returns (string); } From 95411da28934e57168973cd06f10835eb71f28ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:56:58 -0300 Subject: [PATCH 139/205] Renamed internal ERC721 check function. (#1445) (cherry picked from commit 384dff9abeee277f3357b8c472ef38a5ec825df3) --- contracts/token/ERC721/ERC721.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index eeee146e2..3dc243874 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -200,7 +200,7 @@ contract ERC721 is ERC165, IERC721 { { transferFrom(from, to, tokenId); // solium-disable-next-line arg-overflow - require(_checkAndCallSafeTransfer(from, to, tokenId, _data)); + require(_checkOnERC721Received(from, to, tokenId, _data)); } /** @@ -306,7 +306,7 @@ contract ERC721 is ERC165, IERC721 { * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ - function _checkAndCallSafeTransfer( + function _checkOnERC721Received( address from, address to, uint256 tokenId, From 6e53c4e129a0a022feaebe1a1ddb7b77779f6f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 16:57:16 -0300 Subject: [PATCH 140/205] Crowdsale docs improvements. (#1446) * Added a small Crowdsale fallback gas warning. * Fixed a couple typos. (cherry picked from commit 94692acb146b4204d7a57b604f160e46dba9c2cd) --- contracts/crowdsale/Crowdsale.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index f425718fd..9aa550519 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -73,6 +73,9 @@ contract Crowdsale { /** * @dev fallback function ***DO NOT OVERRIDE*** + * Note that other contracts will transfer fund with a base gas stipend + * of 2300, which is not enough to call buyTokens. Consider calling + * buyTokens directly when purchasing tokens from a contract. */ function () external payable { buyTokens(msg.sender); @@ -100,7 +103,7 @@ contract Crowdsale { } /** - * @return the mount of wei raised. + * @return the amount of wei raised. */ function weiRaised() public view returns (uint256) { return _weiRaised; @@ -108,7 +111,7 @@ contract Crowdsale { /** * @dev low level token purchase ***DO NOT OVERRIDE*** - * @param beneficiary Address performing the token purchase + * @param beneficiary Recipient of the token purchase */ function buyTokens(address beneficiary) public payable { @@ -188,7 +191,7 @@ contract Crowdsale { } /** - * @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens. + * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens. * @param beneficiary Address receiving the tokens * @param tokenAmount Number of tokens to be purchased */ From a9bffb37872b55f94465b417a735bb9da2233189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:42:57 -0300 Subject: [PATCH 141/205] Now setting the finalized flag before doing finalization to prevent possbile reentrancy issues. (#1447) (cherry picked from commit 5bb865218f02a01d0521c9d9a947cdf4bd32e74c) --- contracts/crowdsale/distribution/FinalizableCrowdsale.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index bcdfa4563..8add165da 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -34,10 +34,10 @@ contract FinalizableCrowdsale is TimedCrowdsale { require(!_finalized); require(hasClosed()); + _finalized = true; + _finalization(); emit CrowdsaleFinalized(); - - _finalized = true; } /** @@ -47,5 +47,4 @@ contract FinalizableCrowdsale is TimedCrowdsale { */ function _finalization() internal { } - } From 5cdf4de1f676d5bc17cce902202fe93241c19f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:43:12 -0300 Subject: [PATCH 142/205] Made SampleCrowdsale a bit clearer. (#1448) --- contracts/examples/SampleCrowdsale.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 6e1272223..d22598092 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -4,17 +4,15 @@ import "../crowdsale/validation/CappedCrowdsale.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; import "../token/ERC20/ERC20Mintable.sol"; +import "../token/ERC20/ERC20Detailed.sol"; /** * @title SampleCrowdsaleToken * @dev Very simple ERC20 Token that can be minted. * It is meant to be used in a crowdsale contract. */ -contract SampleCrowdsaleToken is ERC20Mintable { - - string public constant name = "Sample Crowdsale Token"; - string public constant symbol = "SCT"; - uint8 public constant decimals = 18; +contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { + constructor() public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {} } /** @@ -24,6 +22,8 @@ contract SampleCrowdsaleToken is ERC20Mintable { * In this example we are providing following extensions: * CappedCrowdsale - sets a max boundary for raised funds * RefundableCrowdsale - set a min goal to be reached and returns funds if it's not met + * MintedCrowdsale - assumes the token can be minted by the crowdsale, which does so + * when receiving purchases. * * After adding multiple features it's good practice to run integration tests * to ensure that subcontracts works together as intended. From 984fe23a4657650112f1d707082b7b4ba319b0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 18:43:44 -0300 Subject: [PATCH 143/205] Deleted unnecessary import. (#1437) * Deleted unnecessary import. * Added back SafeMath. * Removed another unnecessary import. (cherry picked from commit bbe804a14bf901bc5f1742ec58665d4b5fd1a2c4) --- contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol | 1 - contracts/token/ERC20/SafeERC20.sol | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index ca05f6d66..b8c9ede77 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -1,7 +1,6 @@ pragma solidity ^0.4.24; import "../validation/TimedCrowdsale.sol"; -import "../../token/ERC20/IERC20.sol"; import "../../math/SafeMath.sol"; /** diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 9e6bf6a20..2774afa08 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "./ERC20.sol"; import "./IERC20.sol"; +import "../../math/SafeMath.sol"; /** * @title SafeERC20 From 47b5d61844972b3e8ab178f95b37184bbb2e9d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 15:12:16 -0300 Subject: [PATCH 144/205] Fixed how allowance crowdsale checks remaining tokens. (#1449) (cherry picked from commit 1ac1ac984ec3f5ab10d01150480670f30ecb4fc0) --- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 6 +++++- test/crowdsale/AllowanceCrowdsale.test.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index ec9918feb..346275c7d 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -4,6 +4,7 @@ import "../Crowdsale.sol"; import "../../token/ERC20/IERC20.sol"; import "../../token/ERC20/SafeERC20.sol"; import "../../math/SafeMath.sol"; +import "../../math/Math.sol"; /** * @title AllowanceCrowdsale @@ -36,7 +37,10 @@ contract AllowanceCrowdsale is Crowdsale { * @return Amount of tokens left in the allowance */ function remainingTokens() public view returns (uint256) { - return token().allowance(_tokenWallet, this); + return Math.min( + token().balanceOf(_tokenWallet), + token().allowance(_tokenWallet, this) + ); } /** diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 4298dcce6..413d25544 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -69,6 +69,17 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); (await this.crowdsale.remainingTokens()).should.be.bignumber.equal(remainingAllowance); }); + + context('when the allowance is larger than the token amount', function () { + beforeEach(async function () { + const amount = await this.token.balanceOf(tokenWallet); + await this.token.approve(this.crowdsale.address, amount.plus(1), { from: tokenWallet }); + }); + + it('should report the amount instead of the allowance', async function () { + (await this.crowdsale.remainingTokens()).should.be.bignumber.equal(await this.token.balanceOf(tokenWallet)); + }); + }); }); describe('when token wallet is different from token address', function () { From ecae7608f9a1eb8af0c66c393d98edac703c3d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 15:37:24 -0300 Subject: [PATCH 145/205] InitialRate must be strictly larger than finalRate. (#1441) (cherry picked from commit a936cbf5fbe78fb160a2fa679cdf434cbed95426) --- .../crowdsale/price/IncreasingPriceCrowdsale.sol | 10 +++++++++- test/crowdsale/IncreasingPriceCrowdsale.test.js | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 4d2b44931..c86353c0f 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -22,11 +22,19 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { */ constructor(uint256 initialRate, uint256 finalRate) internal { require(finalRate > 0); - require(initialRate >= finalRate); + require(initialRate > finalRate); _initialRate = initialRate; _finalRate = finalRate; } + /** + * The base rate function is overridden to revert, since this crowdsale doens't use it, and + * all calls to it are a mistake. + */ + function rate() public view returns(uint256) { + revert(); + } + /** * @return the initial rate of the crowdsale. */ diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 51946b5ee..41906d224 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -34,13 +34,19 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) this.token = await SimpleToken.new(); }); - it('rejects a final rate larger than the initial rate', async function () { + it('reverts with a final rate larger than the initial rate', async function () { await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate.plus(1) )); }); - it('rejects a final rate of zero', async function () { + it('reverts with a final equal to the initial rate', async function () { + await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( + this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate + )); + }); + + it('reverts with a final rate of zero', async function () { await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new( this.startTime, this.closingTime, wallet, this.token.address, initialRate, 0 )); @@ -59,6 +65,10 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) (await this.crowdsale.finalRate()).should.be.bignumber.equal(finalRate); }); + it('reverts when the base Crowdsale\'s rate function is called', async function () { + await shouldFail.reverting(this.crowdsale.rate()); + }); + it('returns a rate of 0 before the crowdsale starts', async function () { (await this.crowdsale.getCurrentRate()).should.be.bignumber.equal(0); }); From 1a4009f817e2d514fb6399441cd66a82ea983cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 19 Oct 2018 17:42:20 -0300 Subject: [PATCH 146/205] Crowdsale.buyTokens is now nonReentrant. (#1438) (cherry picked from commit 6d415c508be94ef8391ed6525df365452466da76) --- contracts/crowdsale/Crowdsale.sol | 7 +++++-- contracts/utils/ReentrancyGuard.sol | 9 ++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index 9aa550519..a0c227607 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.24; import "../token/ERC20/IERC20.sol"; import "../math/SafeMath.sol"; import "../token/ERC20/SafeERC20.sol"; +import "../utils/ReentrancyGuard.sol"; /** * @title Crowdsale @@ -16,7 +17,7 @@ import "../token/ERC20/SafeERC20.sol"; * the methods to add functionality. Consider using 'super' where appropriate to concatenate * behavior. */ -contract Crowdsale { +contract Crowdsale is ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for IERC20; @@ -111,9 +112,11 @@ contract Crowdsale { /** * @dev low level token purchase ***DO NOT OVERRIDE*** + * This function has a non-reentrancy guard, so it shouldn't be called by + * another `nonReentrant` function. * @param beneficiary Recipient of the token purchase */ - function buyTokens(address beneficiary) public payable { + function buyTokens(address beneficiary) public nonReentrant payable { uint256 weiAmount = msg.value; _preValidatePurchase(beneficiary, weiAmount); diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 368f2720f..7a2895da2 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -19,11 +19,10 @@ contract ReentrancyGuard { /** * @dev Prevents a contract from calling itself, directly or indirectly. - * If you mark a function `nonReentrant`, you should also - * mark it `external`. Calling one `nonReentrant` function from - * another is not supported. Instead, you can implement a - * `private` function doing the actual work, and an `external` - * wrapper marked as `nonReentrant`. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and make it call a + * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; From ae339333d7d160f42fae3944033ec53075a6f7ab Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 19 Oct 2018 17:35:04 -0600 Subject: [PATCH 147/205] Add warning about trading tokens before refundable crowdsale goal is met (#1452) This attack was reported in https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 (cherry picked from commit 80458ebc72f1c7c9695416edbe26690f72e406a0) --- .../crowdsale/distribution/RefundableCrowdsale.sol | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index d670f9ced..9b814cd7d 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -8,6 +8,19 @@ import "../../payment/escrow/RefundEscrow.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. + * WARNING: note that if you allow tokens to be traded before the goal + * is met, then an attack is possible in which the attacker purchases + * tokens from the crowdsale and when they sees that the goal is + * unlikely to be met, they sell their tokens (possibly at a discount). + * The attacker will be refunded when the crowdsale is finalized, and + * the users that purchased from them will be left with worthless + * tokens. There are many possible ways to avoid this, like making the + * the crowdsale inherit from PostDeliveryCrowdsale, or imposing + * restrictions on token trading until the crowdsale is finalized. + * This is being discussed in + * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 + * This contract will be updated when we agree on a general solution + * for this problem. */ contract RefundableCrowdsale is FinalizableCrowdsale { using SafeMath for uint256; From 643ac86d0a32546ecc69e9ff22add16fba4bbbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 18 Oct 2018 19:07:34 -0300 Subject: [PATCH 148/205] Improved some ERC721 internal shenanigans (#1450) * Made _clearApproval private, added clarifying comments in _addTokenTo and _removeTokenFrom. * Added approval information. (cherry picked from commit 8204f6a71fcb1597e3c92117290600f4e752ca19) --- contracts/token/ERC721/ERC721.sol | 31 ++++++++++++--------- contracts/token/ERC721/ERC721Enumerable.sol | 5 ++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 3dc243874..ec0763b96 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -262,21 +262,10 @@ contract ERC721 is ERC165, IERC721 { emit Transfer(owner, address(0), tokenId); } - /** - * @dev Internal function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param owner owner of the token - * @param tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(address owner, uint256 tokenId) internal { - require(ownerOf(tokenId) == owner); - if (_tokenApprovals[tokenId] != address(0)) { - _tokenApprovals[tokenId] = address(0); - } - } - /** * @dev Internal function to add a token ID to the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ @@ -288,6 +277,9 @@ contract ERC721 is ERC165, IERC721 { /** * @dev Internal function to remove a token ID from the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ @@ -322,4 +314,17 @@ contract ERC721 is ERC165, IERC721 { msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } + + /** + * @dev Private function to clear current approval of a given token ID + * Reverts if the given address is not indeed the owner of the token + * @param owner owner of the token + * @param tokenId uint256 ID of the token to be transferred + */ + function _clearApproval(address owner, uint256 tokenId) private { + require(ownerOf(tokenId) == owner); + if (_tokenApprovals[tokenId] != address(0)) { + _tokenApprovals[tokenId] = address(0); + } + } } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index 0a2797eed..c85514720 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -72,6 +72,8 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { /** * @dev Internal function to add a token ID to the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ @@ -84,6 +86,9 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { /** * @dev Internal function to remove a token ID from the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ From 7789814606e6e7a485d386d25ab84f0445246f8f Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Sun, 21 Oct 2018 00:16:09 +0000 Subject: [PATCH 149/205] Release candidate v2.0.0-rc.4 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index ced48af3d..5767c161d 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.0.0-rc.3", + "version": "2.0.0-rc.4", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index bcdabbce1..0330ba8f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0-rc.3", + "version": "2.0.0-rc.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 55697d8e5..a6f9077c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0-rc.3", + "version": "2.0.0-rc.4", "description": "Secure Smart Contract library for Solidity", "files": [ "build", From 06e265b38d3e9daeaa7b33f9035c700d6bc0c6a0 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Sun, 21 Oct 2018 15:33:49 +0000 Subject: [PATCH 150/205] Release v2.0.0 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index 5767c161d..a60b4a603 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.0.0-rc.4", + "version": "2.0.0", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index 0330ba8f9..9e2fe893b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0-rc.4", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a6f9077c1..f97f1050a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0-rc.4", + "version": "2.0.0", "description": "Secure Smart Contract library for Solidity", "files": [ "build", From 18552a8d5ff162184d1c1f9f8fcbef2408df6fac Mon Sep 17 00:00:00 2001 From: "Hao (Alan) Tang" <7888785@qq.com> Date: Thu, 1 Nov 2018 11:15:04 -0700 Subject: [PATCH 151/205] Fix/add comment erc721 burnable #1464 (#1469) * fix Add a comment to ERC721Enumerable #1465 * fix Add comments to ERC721Burnable #1464 --- contracts/token/ERC721/ERC721Burnable.sol | 9 +++++++++ contracts/token/ERC721/ERC721Enumerable.sol | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index 3fc0277e5..71f3bcdd1 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -2,7 +2,16 @@ pragma solidity ^0.4.24; import "./ERC721.sol"; +/** + * @title ERC721 Burnable Token + * @dev ERC721 Token that can be irreversibly burned (destroyed). + */ contract ERC721Burnable is ERC721 { + + /** + * @dev Burns a specific ERC721 token. + * @param tokenId uint256 id of the ERC721 token to be burned. + */ function burn(uint256 tokenId) public { diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index c85514720..234307755 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -4,6 +4,10 @@ import "./IERC721Enumerable.sol"; import "./ERC721.sol"; import "../../introspection/ERC165.sol"; +/** + * @title ERC-721 Non-Fungible Token with optional enumeration extension logic + * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md + */ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; From 79eb94d3cd96e0d65a4fec020fc1218dd3320b76 Mon Sep 17 00:00:00 2001 From: "Hao (Alan) Tang" <7888785@qq.com> Date: Thu, 1 Nov 2018 11:27:51 -0700 Subject: [PATCH 152/205] fix ERC20.sol#L174 and ERC20.sol#L187 should be casted to an address type. (#1470) --- contracts/token/ERC20/ERC20.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 25b2694a2..77a88be62 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -171,7 +171,7 @@ contract ERC20 is IERC20 { * @param value The amount that will be created. */ function _mint(address account, uint256 value) internal { - require(account != 0); + require(account != address(0)); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); @@ -184,7 +184,7 @@ contract ERC20 is IERC20 { * @param value The amount that will be burnt. */ function _burn(address account, uint256 value) internal { - require(account != 0); + require(account != address(0)); require(value <= _balances[account]); _totalSupply = _totalSupply.sub(value); From 4f356e35a9bc38fce13342aeb99544e6512ea477 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Fri, 2 Nov 2018 00:08:54 +0530 Subject: [PATCH 153/205] The beneficiary parameter of claimRefund is replaced with refundee (#1481) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * conflict fixes * fixes #1456 --- contracts/crowdsale/distribution/RefundableCrowdsale.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index 9b814cd7d..da02baee6 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -50,13 +50,13 @@ contract RefundableCrowdsale is FinalizableCrowdsale { /** * @dev Investors can claim refunds here if crowdsale is unsuccessful - * @param beneficiary Whose refund will be claimed. + * @param refundee Whose refund will be claimed. */ - function claimRefund(address beneficiary) public { + function claimRefund(address refundee) public { require(finalized()); require(!goalReached()); - _escrow.withdraw(beneficiary); + _escrow.withdraw(refundee); } /** From b5892a2b5e69aac1a29ef191c2ce100d95b3b322 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Fri, 2 Nov 2018 00:32:36 +0530 Subject: [PATCH 154/205] SafeMath Test Coverage Improved (#1477) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * conflict fixes * fixes #1386 * Update SafeMath.test.js --- test/math/SafeMath.test.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index dcbb4fbb6..47e8559ef 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -53,13 +53,20 @@ contract('SafeMath', function () { (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); }); - it('handles a zero product correctly', async function () { + it('handles a zero product correctly (first number as zero)', async function () { const a = new BigNumber(0); const b = new BigNumber(5678); (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); }); + it('handles a zero product correctly (second number as zero)', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); + + (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); + }); + it('throws a revert error on multiplication overflow', async function () { const a = MAX_UINT256; const b = new BigNumber(2); @@ -76,6 +83,20 @@ contract('SafeMath', function () { (await this.safeMath.div(a, b)).should.be.bignumber.equal(a.div(b)); }); + it('divides zero correctly', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + (await this.safeMath.div(a, b)).should.be.bignumber.equal(0); + }); + + it('returns complete number result on non-even division', async function () { + const a = new BigNumber(7000); + const b = new BigNumber(5678); + + (await this.safeMath.div(a, b)).should.be.bignumber.equal(1); + }); + it('throws a revert error on zero division', async function () { const a = new BigNumber(5678); const b = new BigNumber(0); From 1186520617e7ad74e20137d47212848a9f9d96fc Mon Sep 17 00:00:00 2001 From: LaimeJesus Date: Thu, 1 Nov 2018 16:16:21 -0300 Subject: [PATCH 155/205] add improvement in simpletoken example #1458 (#1473) * add improvement in simpletoken example #1458 * fix not calling decimals get function in initial supply --- contracts/examples/SimpleToken.sol | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/contracts/examples/SimpleToken.sol b/contracts/examples/SimpleToken.sol index 8c63fdd98..04b016a73 100644 --- a/contracts/examples/SimpleToken.sol +++ b/contracts/examples/SimpleToken.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; +import "../token/ERC20/ERC20Detailed.sol"; /** * @title SimpleToken @@ -8,18 +9,14 @@ import "../token/ERC20/ERC20.sol"; * Note they can later distribute these tokens as they wish using `transfer` and other * `ERC20` functions. */ -contract SimpleToken is ERC20 { +contract SimpleToken is ERC20, ERC20Detailed { - string public constant name = "SimpleToken"; - string public constant symbol = "SIM"; - uint8 public constant decimals = 18; - - uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals)); + uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals())); /** * @dev Constructor that gives msg.sender all of existing tokens. */ - constructor() public { + constructor() public ERC20Detailed("SimpleToken", "SIM", 18) { _mint(msg.sender, INITIAL_SUPPLY); } From 32bc7a6fe52f981eb0f0a6601e14ebcb6372c12c Mon Sep 17 00:00:00 2001 From: "Hao (Alan) Tang" <7888785@qq.com> Date: Fri, 2 Nov 2018 02:56:50 -0700 Subject: [PATCH 156/205] add an address typecast to this per issue #1457 (#1471) --- contracts/drafts/TokenVesting.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 2f5fd2fdc..3fa49f79f 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -161,7 +161,7 @@ contract TokenVesting is Ownable { * @param token ERC20 token which is being vested */ function _vestedAmount(IERC20 token) private view returns (uint256) { - uint256 currentBalance = token.balanceOf(this); + uint256 currentBalance = token.balanceOf(address(this)); uint256 totalBalance = currentBalance.add(_released[token]); if (block.timestamp < _cliff) { From f72c79d54a27be376403ec53b1705b09d765aa7f Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 2 Nov 2018 03:59:05 -0600 Subject: [PATCH 157/205] Add the step to delete the build dir to the RELEASE notes (#1467) --- RELEASING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index 40360afcf..7ef7f098f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -36,7 +36,7 @@ Draft the release notes in our [GitHub releases](https://github.com/OpenZeppelin Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. -1. Delete the `contracts/mocks` and `contracts/examples` directories. +1. Delete the `contracts/mocks`, `contracts/examples` and `build` directories. 2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) 3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. @@ -70,7 +70,7 @@ Draft the release notes in GitHub releases. Try to be consistent with our previo Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. -1. Delete the `contracts/mocks` and `contracts/examples` directories. +1. Delete the `contracts/mocks`, `contracts/examples` and `build` directories. 2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) 3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. From 6363a776f7d2a1f8fa19f394ec24b3a2c5cb42a0 Mon Sep 17 00:00:00 2001 From: Brendan Chou Date: Fri, 2 Nov 2018 18:14:06 +0800 Subject: [PATCH 158/205] Remove redundant require statements (#1409) * Remove redundant require statements Now that SafeMath uses require, the require statements are redundant. They were also previously inconsistent because they were only included in some functions, but not others * Update ERC20.sol --- contracts/token/ERC20/ERC20.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 77a88be62..6af870865 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -93,8 +93,6 @@ contract ERC20 is IERC20 { public returns (bool) { - require(value <= _allowed[from][msg.sender]); - _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); _transfer(from, to, value); return true; @@ -155,7 +153,6 @@ contract ERC20 is IERC20 { * @param value The amount to be transferred. */ function _transfer(address from, address to, uint256 value) internal { - require(value <= _balances[from]); require(to != address(0)); _balances[from] = _balances[from].sub(value); @@ -172,6 +169,7 @@ contract ERC20 is IERC20 { */ function _mint(address account, uint256 value) internal { require(account != address(0)); + _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); @@ -185,7 +183,6 @@ contract ERC20 is IERC20 { */ function _burn(address account, uint256 value) internal { require(account != address(0)); - require(value <= _balances[account]); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); From 83bc045a56d891726ab3a4cbdd6be35e0023e72c Mon Sep 17 00:00:00 2001 From: William Entriken Date: Fri, 2 Nov 2018 06:16:35 -0400 Subject: [PATCH 159/205] Remove extraneous quantity check, fixes #1454 (#1455) --- contracts/token/ERC20/ERC20.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 6af870865..5c550539f 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -197,8 +197,6 @@ contract ERC20 is IERC20 { * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { - require(value <= _allowed[account][msg.sender]); - // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, // this function needs to emit an event with the updated approval. _allowed[account][msg.sender] = _allowed[account][msg.sender].sub( From bb6a24e6aaea80efbfe0606f1422219cedbb6cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 20 Nov 2018 16:03:22 -0300 Subject: [PATCH 160/205] Renamed roles private variables to adhere to code style. (#1507) --- contracts/access/roles/CapperRole.sol | 8 ++++---- contracts/access/roles/MinterRole.sol | 8 ++++---- contracts/access/roles/PauserRole.sol | 8 ++++---- contracts/access/roles/SignerRole.sol | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index d6b2ba066..25c2d7c73 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -8,7 +8,7 @@ contract CapperRole { event CapperAdded(address indexed account); event CapperRemoved(address indexed account); - Roles.Role private cappers; + Roles.Role private _cappers; constructor() internal { _addCapper(msg.sender); @@ -20,7 +20,7 @@ contract CapperRole { } function isCapper(address account) public view returns (bool) { - return cappers.has(account); + return _cappers.has(account); } function addCapper(address account) public onlyCapper { @@ -32,12 +32,12 @@ contract CapperRole { } function _addCapper(address account) internal { - cappers.add(account); + _cappers.add(account); emit CapperAdded(account); } function _removeCapper(address account) internal { - cappers.remove(account); + _cappers.remove(account); emit CapperRemoved(account); } } diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index 57f4a5a80..450f69652 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -8,7 +8,7 @@ contract MinterRole { event MinterAdded(address indexed account); event MinterRemoved(address indexed account); - Roles.Role private minters; + Roles.Role private _minters; constructor() internal { _addMinter(msg.sender); @@ -20,7 +20,7 @@ contract MinterRole { } function isMinter(address account) public view returns (bool) { - return minters.has(account); + return _minters.has(account); } function addMinter(address account) public onlyMinter { @@ -32,12 +32,12 @@ contract MinterRole { } function _addMinter(address account) internal { - minters.add(account); + _minters.add(account); emit MinterAdded(account); } function _removeMinter(address account) internal { - minters.remove(account); + _minters.remove(account); emit MinterRemoved(account); } } diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index 58bb6a313..698bb8769 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -8,7 +8,7 @@ contract PauserRole { event PauserAdded(address indexed account); event PauserRemoved(address indexed account); - Roles.Role private pausers; + Roles.Role private _pausers; constructor() internal { _addPauser(msg.sender); @@ -20,7 +20,7 @@ contract PauserRole { } function isPauser(address account) public view returns (bool) { - return pausers.has(account); + return _pausers.has(account); } function addPauser(address account) public onlyPauser { @@ -32,12 +32,12 @@ contract PauserRole { } function _addPauser(address account) internal { - pausers.add(account); + _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { - pausers.remove(account); + _pausers.remove(account); emit PauserRemoved(account); } } diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index 6a2bc602d..8d76b831f 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -8,7 +8,7 @@ contract SignerRole { event SignerAdded(address indexed account); event SignerRemoved(address indexed account); - Roles.Role private signers; + Roles.Role private _signers; constructor() internal { _addSigner(msg.sender); @@ -20,7 +20,7 @@ contract SignerRole { } function isSigner(address account) public view returns (bool) { - return signers.has(account); + return _signers.has(account); } function addSigner(address account) public onlySigner { @@ -32,12 +32,12 @@ contract SignerRole { } function _addSigner(address account) internal { - signers.add(account); + _signers.add(account); emit SignerAdded(account); } function _removeSigner(address account) internal { - signers.remove(account); + _signers.remove(account); emit SignerRemoved(account); } } From 281338409b9dae5c75ea52c4a5a61c78bc4d768c Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Thu, 22 Nov 2018 18:01:17 +0300 Subject: [PATCH 161/205] Test description fix in ERC20Pausable.test.js (#1501) Small change in test description, should be "allows to approve..." instead of "allow to transfer..." in approve section, where test actualy try to approve, not to transfer. --- test/token/ERC20/ERC20Pausable.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/token/ERC20/ERC20Pausable.test.js b/test/token/ERC20/ERC20Pausable.test.js index 05a0532ed..f89d20e25 100644 --- a/test/token/ERC20/ERC20Pausable.test.js +++ b/test/token/ERC20/ERC20Pausable.test.js @@ -144,7 +144,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA (await this.token.allowance(pauser, anotherAccount)).should.be.bignumber.equal(40); }); - it('allows to transfer when paused and then unpaused', async function () { + it('allows to approve when paused and then unpaused', async function () { await this.token.pause({ from: pauser }); await this.token.unpause({ from: pauser }); @@ -153,7 +153,7 @@ contract('ERC20Pausable', function ([_, pauser, otherPauser, recipient, anotherA (await this.token.allowance(pauser, anotherAccount)).should.be.bignumber.equal(40); }); - it('reverts when trying to transfer when paused', async function () { + it('reverts when trying to approve when paused', async function () { await this.token.pause({ from: pauser }); await shouldFail.reverting(this.token.approve(anotherAccount, 40, { from: pauser })); From 5471fc808a17342d738853d7bf3e9e5ef3108074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 22 Nov 2018 16:53:30 -0300 Subject: [PATCH 162/205] Updated code style to 4 space indentation and 120 characters per line. (#1508) * Updated code style to 4 spaces and 120 max characters per line. * Update contracts/token/ERC721/ERC721Pausable.sol Co-Authored-By: nventuro * Update contracts/token/ERC721/IERC721.sol Co-Authored-By: nventuro --- .soliumrc.json | 5 +- contracts/access/Roles.sol | 58 +- contracts/access/roles/CapperRole.sol | 56 +- contracts/access/roles/MinterRole.sol | 56 +- contracts/access/roles/PauserRole.sol | 56 +- contracts/access/roles/SignerRole.sol | 56 +- contracts/crowdsale/Crowdsale.sol | 346 +++++------ .../distribution/FinalizableCrowdsale.sol | 59 +- .../distribution/PostDeliveryCrowdsale.sol | 61 +- .../distribution/RefundableCrowdsale.sol | 127 ++-- .../crowdsale/emission/AllowanceCrowdsale.sol | 72 +-- .../crowdsale/emission/MintedCrowdsale.sol | 26 +- .../price/IncreasingPriceCrowdsale.sol | 121 ++-- .../crowdsale/validation/CappedCrowdsale.sol | 71 +-- .../IndividuallyCappedCrowdsale.sol | 108 ++-- .../crowdsale/validation/TimedCrowdsale.sol | 122 ++-- contracts/cryptography/ECDSA.sol | 99 ++- contracts/cryptography/MerkleProof.sol | 52 +- contracts/drafts/Counter.sol | 18 +- contracts/drafts/ERC1046/TokenMetadata.sol | 18 +- contracts/drafts/ERC20Migrator.sol | 112 ++-- contracts/drafts/SignatureBouncer.sol | 172 +++--- contracts/drafts/TokenVesting.sol | 294 +++++---- contracts/examples/SampleCrowdsale.sol | 41 +- contracts/examples/SimpleToken.sol | 16 +- contracts/introspection/ERC165.sol | 67 +-- contracts/introspection/ERC165Checker.sol | 233 ++++---- contracts/introspection/IERC165.sol | 18 +- contracts/lifecycle/Pausable.sol | 80 +-- contracts/math/Math.sol | 42 +- contracts/math/SafeMath.sol | 96 +-- contracts/mocks/AddressImpl.sol | 11 +- contracts/mocks/AllowanceCrowdsaleImpl.sol | 18 +- contracts/mocks/ArraysImpl.sol | 17 +- contracts/mocks/CappedCrowdsaleImpl.sol | 18 +- contracts/mocks/CapperRoleMock.sol | 18 +- contracts/mocks/ConditionalEscrowMock.sol | 14 +- contracts/mocks/CounterImpl.sol | 19 +- contracts/mocks/CrowdsaleMock.sol | 4 +- contracts/mocks/DetailedERC20Mock.sol | 9 +- contracts/mocks/ECDSAMock.sol | 22 +- .../ERC165/ERC165InterfacesSupported.sol | 77 +-- contracts/mocks/ERC165/ERC165NotSupported.sol | 4 +- contracts/mocks/ERC165CheckerMock.sol | 32 +- contracts/mocks/ERC165Mock.sol | 8 +- contracts/mocks/ERC20BurnableMock.sol | 8 +- contracts/mocks/ERC20Mock.sol | 26 +- contracts/mocks/ERC20PausableMock.sol | 8 +- contracts/mocks/ERC20WithMetadataMock.sol | 5 +- contracts/mocks/ERC721FullMock.sol | 27 +- .../mocks/ERC721MintableBurnableImpl.sol | 11 +- contracts/mocks/ERC721Mock.sol | 12 +- contracts/mocks/ERC721PausableMock.sol | 18 +- contracts/mocks/ERC721ReceiverMock.sol | 44 +- contracts/mocks/EventEmitter.sol | 88 ++- contracts/mocks/FinalizableCrowdsaleImpl.sol | 18 +- .../mocks/IncreasingPriceCrowdsaleImpl.sol | 29 +- .../mocks/IndividuallyCappedCrowdsaleImpl.sol | 15 +- contracts/mocks/MathMock.sol | 18 +- contracts/mocks/MerkleProofWrapper.sol | 15 +- contracts/mocks/MintedCrowdsaleImpl.sol | 12 +- contracts/mocks/MinterRoleMock.sol | 18 +- contracts/mocks/OwnableMock.sol | 3 +- contracts/mocks/PausableMock.sol | 25 +- contracts/mocks/PauserRoleMock.sol | 18 +- contracts/mocks/PostDeliveryCrowdsaleImpl.sol | 19 +- contracts/mocks/PullPaymentMock.sol | 12 +- contracts/mocks/ReentrancyAttack.sol | 8 +- contracts/mocks/ReentrancyMock.sol | 58 +- contracts/mocks/RefundableCrowdsaleImpl.sol | 29 +- contracts/mocks/RolesMock.sol | 22 +- contracts/mocks/SafeERC20Helper.sol | 148 ++--- contracts/mocks/SafeMathMock.sol | 31 +- contracts/mocks/SecondaryMock.sol | 3 +- contracts/mocks/SignatureBouncerMock.sol | 73 +-- contracts/mocks/SignerRoleMock.sol | 18 +- contracts/mocks/TimedCrowdsaleImpl.sol | 19 +- contracts/ownership/Ownable.sol | 113 ++-- contracts/ownership/Secondary.sol | 68 +-- contracts/payment/PaymentSplitter.sol | 168 +++--- contracts/payment/PullPayment.sol | 52 +- .../payment/escrow/ConditionalEscrow.sol | 20 +- contracts/payment/escrow/Escrow.sol | 52 +- contracts/payment/escrow/RefundEscrow.sol | 128 ++-- contracts/token/ERC20/ERC20.sol | 313 +++++----- contracts/token/ERC20/ERC20Burnable.sol | 31 +- contracts/token/ERC20/ERC20Capped.sol | 33 +- contracts/token/ERC20/ERC20Detailed.sol | 52 +- contracts/token/ERC20/ERC20Mintable.sol | 27 +- contracts/token/ERC20/ERC20Pausable.sol | 67 +-- contracts/token/ERC20/IERC20.sol | 27 +- contracts/token/ERC20/SafeERC20.sol | 76 +-- contracts/token/ERC20/TokenTimelock.sol | 90 ++- contracts/token/ERC721/ERC721.sol | 564 ++++++++---------- contracts/token/ERC721/ERC721Burnable.sol | 19 +- contracts/token/ERC721/ERC721Enumerable.sol | 237 ++++---- contracts/token/ERC721/ERC721Full.sol | 5 +- contracts/token/ERC721/ERC721Holder.sol | 14 +- contracts/token/ERC721/ERC721Metadata.sol | 146 ++--- .../token/ERC721/ERC721MetadataMintable.sol | 32 +- contracts/token/ERC721/ERC721Mintable.sol | 27 +- contracts/token/ERC721/ERC721Pausable.sol | 37 +- contracts/token/ERC721/IERC721.sol | 46 +- contracts/token/ERC721/IERC721Enumerable.sol | 12 +- contracts/token/ERC721/IERC721Metadata.sol | 6 +- contracts/token/ERC721/IERC721Receiver.sol | 37 +- contracts/utils/Address.sol | 40 +- contracts/utils/Arrays.sol | 78 ++- contracts/utils/ReentrancyGuard.sol | 42 +- 109 files changed, 2917 insertions(+), 3629 deletions(-) diff --git a/.soliumrc.json b/.soliumrc.json index 8fe25b30e..e7f413f9f 100644 --- a/.soliumrc.json +++ b/.soliumrc.json @@ -2,12 +2,13 @@ "extends": "solium:all", "plugins": ["security"], "rules": { + "arg-overflow": "off", "blank-lines": "off", "error-reason": "off", - "indentation": ["error", 2], + "indentation": ["error", 4], "lbrace": "off", "linebreak-style": ["error", "unix"], - "max-len": ["error", 79], + "max-len": ["error", 120], "no-constant": ["error"], "no-empty-blocks": "off", "quotes": ["error", "double"], diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index e3b97ddb7..7b364da53 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -5,40 +5,36 @@ pragma solidity ^0.4.24; * @dev Library for managing addresses assigned to a Role. */ library Roles { - struct Role { - mapping (address => bool) bearer; - } + struct Role { + mapping (address => bool) bearer; + } - /** - * @dev give an account access to this role - */ - function add(Role storage role, address account) internal { - require(account != address(0)); - require(!has(role, account)); + /** + * @dev give an account access to this role + */ + function add(Role storage role, address account) internal { + require(account != address(0)); + require(!has(role, account)); - role.bearer[account] = true; - } + role.bearer[account] = true; + } - /** - * @dev remove an account's access to this role - */ - function remove(Role storage role, address account) internal { - require(account != address(0)); - require(has(role, account)); + /** + * @dev remove an account's access to this role + */ + function remove(Role storage role, address account) internal { + require(account != address(0)); + require(has(role, account)); - role.bearer[account] = false; - } + role.bearer[account] = false; + } - /** - * @dev check if an account has this role - * @return bool - */ - function has(Role storage role, address account) - internal - view - returns (bool) - { - require(account != address(0)); - return role.bearer[account]; - } + /** + * @dev check if an account has this role + * @return bool + */ + function has(Role storage role, address account) internal view returns (bool) { + require(account != address(0)); + return role.bearer[account]; + } } diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index 25c2d7c73..7307abce1 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -3,41 +3,41 @@ pragma solidity ^0.4.24; import "../Roles.sol"; contract CapperRole { - using Roles for Roles.Role; + using Roles for Roles.Role; - event CapperAdded(address indexed account); - event CapperRemoved(address indexed account); + event CapperAdded(address indexed account); + event CapperRemoved(address indexed account); - Roles.Role private _cappers; + Roles.Role private _cappers; - constructor() internal { - _addCapper(msg.sender); - } + constructor () internal { + _addCapper(msg.sender); + } - modifier onlyCapper() { - require(isCapper(msg.sender)); - _; - } + modifier onlyCapper() { + require(isCapper(msg.sender)); + _; + } - function isCapper(address account) public view returns (bool) { - return _cappers.has(account); - } + function isCapper(address account) public view returns (bool) { + return _cappers.has(account); + } - function addCapper(address account) public onlyCapper { - _addCapper(account); - } + function addCapper(address account) public onlyCapper { + _addCapper(account); + } - function renounceCapper() public { - _removeCapper(msg.sender); - } + function renounceCapper() public { + _removeCapper(msg.sender); + } - function _addCapper(address account) internal { - _cappers.add(account); - emit CapperAdded(account); - } + function _addCapper(address account) internal { + _cappers.add(account); + emit CapperAdded(account); + } - function _removeCapper(address account) internal { - _cappers.remove(account); - emit CapperRemoved(account); - } + function _removeCapper(address account) internal { + _cappers.remove(account); + emit CapperRemoved(account); + } } diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index 450f69652..c4234c5bc 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -3,41 +3,41 @@ pragma solidity ^0.4.24; import "../Roles.sol"; contract MinterRole { - using Roles for Roles.Role; + using Roles for Roles.Role; - event MinterAdded(address indexed account); - event MinterRemoved(address indexed account); + event MinterAdded(address indexed account); + event MinterRemoved(address indexed account); - Roles.Role private _minters; + Roles.Role private _minters; - constructor() internal { - _addMinter(msg.sender); - } + constructor () internal { + _addMinter(msg.sender); + } - modifier onlyMinter() { - require(isMinter(msg.sender)); - _; - } + modifier onlyMinter() { + require(isMinter(msg.sender)); + _; + } - function isMinter(address account) public view returns (bool) { - return _minters.has(account); - } + function isMinter(address account) public view returns (bool) { + return _minters.has(account); + } - function addMinter(address account) public onlyMinter { - _addMinter(account); - } + function addMinter(address account) public onlyMinter { + _addMinter(account); + } - function renounceMinter() public { - _removeMinter(msg.sender); - } + function renounceMinter() public { + _removeMinter(msg.sender); + } - function _addMinter(address account) internal { - _minters.add(account); - emit MinterAdded(account); - } + function _addMinter(address account) internal { + _minters.add(account); + emit MinterAdded(account); + } - function _removeMinter(address account) internal { - _minters.remove(account); - emit MinterRemoved(account); - } + function _removeMinter(address account) internal { + _minters.remove(account); + emit MinterRemoved(account); + } } diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index 698bb8769..5963feffd 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -3,41 +3,41 @@ pragma solidity ^0.4.24; import "../Roles.sol"; contract PauserRole { - using Roles for Roles.Role; + using Roles for Roles.Role; - event PauserAdded(address indexed account); - event PauserRemoved(address indexed account); + event PauserAdded(address indexed account); + event PauserRemoved(address indexed account); - Roles.Role private _pausers; + Roles.Role private _pausers; - constructor() internal { - _addPauser(msg.sender); - } + constructor () internal { + _addPauser(msg.sender); + } - modifier onlyPauser() { - require(isPauser(msg.sender)); - _; - } + modifier onlyPauser() { + require(isPauser(msg.sender)); + _; + } - function isPauser(address account) public view returns (bool) { - return _pausers.has(account); - } + function isPauser(address account) public view returns (bool) { + return _pausers.has(account); + } - function addPauser(address account) public onlyPauser { - _addPauser(account); - } + function addPauser(address account) public onlyPauser { + _addPauser(account); + } - function renouncePauser() public { - _removePauser(msg.sender); - } + function renouncePauser() public { + _removePauser(msg.sender); + } - function _addPauser(address account) internal { - _pausers.add(account); - emit PauserAdded(account); - } + function _addPauser(address account) internal { + _pausers.add(account); + emit PauserAdded(account); + } - function _removePauser(address account) internal { - _pausers.remove(account); - emit PauserRemoved(account); - } + function _removePauser(address account) internal { + _pausers.remove(account); + emit PauserRemoved(account); + } } diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index 8d76b831f..0dc182705 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -3,41 +3,41 @@ pragma solidity ^0.4.24; import "../Roles.sol"; contract SignerRole { - using Roles for Roles.Role; + using Roles for Roles.Role; - event SignerAdded(address indexed account); - event SignerRemoved(address indexed account); + event SignerAdded(address indexed account); + event SignerRemoved(address indexed account); - Roles.Role private _signers; + Roles.Role private _signers; - constructor() internal { - _addSigner(msg.sender); - } + constructor () internal { + _addSigner(msg.sender); + } - modifier onlySigner() { - require(isSigner(msg.sender)); - _; - } + modifier onlySigner() { + require(isSigner(msg.sender)); + _; + } - function isSigner(address account) public view returns (bool) { - return _signers.has(account); - } + function isSigner(address account) public view returns (bool) { + return _signers.has(account); + } - function addSigner(address account) public onlySigner { - _addSigner(account); - } + function addSigner(address account) public onlySigner { + _addSigner(account); + } - function renounceSigner() public { - _removeSigner(msg.sender); - } + function renounceSigner() public { + _removeSigner(msg.sender); + } - function _addSigner(address account) internal { - _signers.add(account); - emit SignerAdded(account); - } + function _addSigner(address account) internal { + _signers.add(account); + emit SignerAdded(account); + } - function _removeSigner(address account) internal { - _signers.remove(account); - emit SignerRemoved(account); - } + function _removeSigner(address account) internal { + _signers.remove(account); + emit SignerRemoved(account); + } } diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index a0c227607..451f902de 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -18,224 +18,184 @@ import "../utils/ReentrancyGuard.sol"; * behavior. */ contract Crowdsale is ReentrancyGuard { - using SafeMath for uint256; - using SafeERC20 for IERC20; + using SafeMath for uint256; + using SafeERC20 for IERC20; - // The token being sold - IERC20 private _token; + // The token being sold + IERC20 private _token; - // Address where funds are collected - address private _wallet; + // Address where funds are collected + address private _wallet; - // How many token units a buyer gets per wei. - // The rate is the conversion between wei and the smallest and indivisible token unit. - // So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK - // 1 wei will give you 1 unit, or 0.001 TOK. - uint256 private _rate; + // How many token units a buyer gets per wei. + // The rate is the conversion between wei and the smallest and indivisible token unit. + // So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK + // 1 wei will give you 1 unit, or 0.001 TOK. + uint256 private _rate; - // Amount of wei raised - uint256 private _weiRaised; + // Amount of wei raised + uint256 private _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 TokensPurchased( - address indexed purchaser, - address indexed beneficiary, - uint256 value, - uint256 amount - ); + /** + * 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 TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount); - /** - * @param rate Number of token units a buyer gets per wei - * @dev The rate is the conversion between wei and the smallest and indivisible - * token unit. So, if you are using a rate of 1 with a ERC20Detailed token - * with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK. - * @param wallet Address where collected funds will be forwarded to - * @param token Address of the token being sold - */ - constructor(uint256 rate, address wallet, IERC20 token) internal { - require(rate > 0); - require(wallet != address(0)); - require(token != address(0)); + /** + * @param rate Number of token units a buyer gets per wei + * @dev The rate is the conversion between wei and the smallest and indivisible + * token unit. So, if you are using a rate of 1 with a ERC20Detailed token + * with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK. + * @param wallet Address where collected funds will be forwarded to + * @param token Address of the token being sold + */ + constructor (uint256 rate, address wallet, IERC20 token) internal { + require(rate > 0); + require(wallet != address(0)); + require(token != address(0)); - _rate = rate; - _wallet = wallet; - _token = token; - } + _rate = rate; + _wallet = wallet; + _token = token; + } - // ----------------------------------------- - // Crowdsale external interface - // ----------------------------------------- + // ----------------------------------------- + // Crowdsale external interface + // ----------------------------------------- - /** - * @dev fallback function ***DO NOT OVERRIDE*** - * Note that other contracts will transfer fund with a base gas stipend - * of 2300, which is not enough to call buyTokens. Consider calling - * buyTokens directly when purchasing tokens from a contract. - */ - function () external payable { - buyTokens(msg.sender); - } + /** + * @dev fallback function ***DO NOT OVERRIDE*** + * Note that other contracts will transfer fund with a base gas stipend + * of 2300, which is not enough to call buyTokens. Consider calling + * buyTokens directly when purchasing tokens from a contract. + */ + function () external payable { + buyTokens(msg.sender); + } - /** - * @return the token being sold. - */ - function token() public view returns(IERC20) { - return _token; - } + /** + * @return the token being sold. + */ + function token() public view returns (IERC20) { + return _token; + } - /** - * @return the address where funds are collected. - */ - function wallet() public view returns(address) { - return _wallet; - } + /** + * @return the address where funds are collected. + */ + function wallet() public view returns (address) { + return _wallet; + } - /** - * @return the number of token units a buyer gets per wei. - */ - function rate() public view returns(uint256) { - return _rate; - } + /** + * @return the number of token units a buyer gets per wei. + */ + function rate() public view returns (uint256) { + return _rate; + } - /** - * @return the amount of wei raised. - */ - function weiRaised() public view returns (uint256) { - return _weiRaised; - } + /** + * @return the amount of wei raised. + */ + function weiRaised() public view returns (uint256) { + return _weiRaised; + } - /** - * @dev low level token purchase ***DO NOT OVERRIDE*** - * This function has a non-reentrancy guard, so it shouldn't be called by - * another `nonReentrant` function. - * @param beneficiary Recipient of the token purchase - */ - function buyTokens(address beneficiary) public nonReentrant payable { + /** + * @dev low level token purchase ***DO NOT OVERRIDE*** + * This function has a non-reentrancy guard, so it shouldn't be called by + * another `nonReentrant` function. + * @param beneficiary Recipient of the token purchase + */ + function buyTokens(address beneficiary) public nonReentrant payable { + uint256 weiAmount = msg.value; + _preValidatePurchase(beneficiary, weiAmount); - uint256 weiAmount = msg.value; - _preValidatePurchase(beneficiary, weiAmount); + // calculate token amount to be created + uint256 tokens = _getTokenAmount(weiAmount); - // calculate token amount to be created - uint256 tokens = _getTokenAmount(weiAmount); + // update state + _weiRaised = _weiRaised.add(weiAmount); - // update state - _weiRaised = _weiRaised.add(weiAmount); + _processPurchase(beneficiary, tokens); + emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens); - _processPurchase(beneficiary, tokens); - emit TokensPurchased( - msg.sender, - beneficiary, - weiAmount, - tokens - ); + _updatePurchasingState(beneficiary, weiAmount); - _updatePurchasingState(beneficiary, weiAmount); + _forwardFunds(); + _postValidatePurchase(beneficiary, weiAmount); + } - _forwardFunds(); - _postValidatePurchase(beneficiary, weiAmount); - } + // ----------------------------------------- + // Internal interface (extensible) + // ----------------------------------------- - // ----------------------------------------- - // Internal interface (extensible) - // ----------------------------------------- + /** + * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations. + * Example from CappedCrowdsale.sol's _preValidatePurchase method: + * super._preValidatePurchase(beneficiary, weiAmount); + * require(weiRaised().add(weiAmount) <= cap); + * @param beneficiary Address performing the token purchase + * @param weiAmount Value in wei involved in the purchase + */ + function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { + require(beneficiary != address(0)); + require(weiAmount != 0); + } - /** - * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations. - * Example from CappedCrowdsale.sol's _preValidatePurchase method: - * super._preValidatePurchase(beneficiary, weiAmount); - * require(weiRaised().add(weiAmount) <= cap); - * @param beneficiary Address performing the token purchase - * @param weiAmount Value in wei involved in the purchase - */ - function _preValidatePurchase( - address beneficiary, - uint256 weiAmount - ) - internal - view - { - require(beneficiary != address(0)); - require(weiAmount != 0); - } + /** + * @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met. + * @param beneficiary Address performing the token purchase + * @param weiAmount Value in wei involved in the purchase + */ + function _postValidatePurchase(address beneficiary, uint256 weiAmount) internal view { + // optional override + } - /** - * @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met. - * @param beneficiary Address performing the token purchase - * @param weiAmount Value in wei involved in the purchase - */ - function _postValidatePurchase( - address beneficiary, - uint256 weiAmount - ) - internal - view - { - // optional override - } + /** + * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens. + * @param beneficiary Address performing the token purchase + * @param tokenAmount Number of tokens to be emitted + */ + function _deliverTokens(address beneficiary, uint256 tokenAmount) internal { + _token.safeTransfer(beneficiary, tokenAmount); + } - /** - * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens. - * @param beneficiary Address performing the token purchase - * @param tokenAmount Number of tokens to be emitted - */ - function _deliverTokens( - address beneficiary, - uint256 tokenAmount - ) - internal - { - _token.safeTransfer(beneficiary, tokenAmount); - } + /** + * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens. + * @param beneficiary Address receiving the tokens + * @param tokenAmount Number of tokens to be purchased + */ + function _processPurchase(address beneficiary, uint256 tokenAmount) internal { + _deliverTokens(beneficiary, tokenAmount); + } - /** - * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens. - * @param beneficiary Address receiving the tokens - * @param tokenAmount Number of tokens to be purchased - */ - function _processPurchase( - address beneficiary, - uint256 tokenAmount - ) - internal - { - _deliverTokens(beneficiary, tokenAmount); - } + /** + * @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.) + * @param beneficiary Address receiving the tokens + * @param weiAmount Value in wei involved in the purchase + */ + function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal { + // optional override + } - /** - * @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.) - * @param beneficiary Address receiving the tokens - * @param weiAmount Value in wei involved in the purchase - */ - function _updatePurchasingState( - address beneficiary, - uint256 weiAmount - ) - internal - { - // optional override - } + /** + * @dev Override to extend the way in which ether is converted to tokens. + * @param weiAmount Value in wei to be converted into tokens + * @return Number of tokens that can be purchased with the specified _weiAmount + */ + function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) { + return weiAmount.mul(_rate); + } - /** - * @dev Override to extend the way in which ether is converted to tokens. - * @param weiAmount Value in wei to be converted into tokens - * @return Number of tokens that can be purchased with the specified _weiAmount - */ - function _getTokenAmount(uint256 weiAmount) - internal view returns (uint256) - { - return weiAmount.mul(_rate); - } - - /** - * @dev Determines how ETH is stored/forwarded on purchases. - */ - function _forwardFunds() internal { - _wallet.transfer(msg.value); - } + /** + * @dev Determines how ETH is stored/forwarded on purchases. + */ + function _forwardFunds() internal { + _wallet.transfer(msg.value); + } } diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index 8add165da..22ae5ba05 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -9,42 +9,41 @@ import "../validation/TimedCrowdsale.sol"; * can do extra work after finishing. */ contract FinalizableCrowdsale is TimedCrowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - bool private _finalized; + bool private _finalized; - event CrowdsaleFinalized(); + event CrowdsaleFinalized(); - constructor() internal { - _finalized = false; - } + constructor () internal { + _finalized = false; + } - /** - * @return true if the crowdsale is finalized, false otherwise. - */ - function finalized() public view returns (bool) { - return _finalized; - } + /** + * @return true if the crowdsale is finalized, false otherwise. + */ + function finalized() public view returns (bool) { + return _finalized; + } - /** - * @dev Must be called after crowdsale ends, to do some extra finalization - * work. Calls the contract's finalization function. - */ - function finalize() public { - require(!_finalized); - require(hasClosed()); + /** + * @dev Must be called after crowdsale ends, to do some extra finalization + * work. Calls the contract's finalization function. + */ + function finalize() public { + require(!_finalized); + require(hasClosed()); - _finalized = true; + _finalized = true; - _finalization(); - emit CrowdsaleFinalized(); - } + _finalization(); + emit CrowdsaleFinalized(); + } - /** - * @dev Can be overridden to add finalization logic. The overriding function - * should call super._finalization() to ensure the chain of finalization is - * executed entirely. - */ - function _finalization() internal { - } + /** + * @dev Can be overridden to add finalization logic. The overriding function + * should call super._finalization() to ensure the chain of finalization is + * executed entirely. + */ + function _finalization() internal {} } diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index b8c9ede77..9d4de3b09 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -8,43 +8,38 @@ import "../../math/SafeMath.sol"; * @dev Crowdsale that locks tokens from withdrawal until it ends. */ contract PostDeliveryCrowdsale is TimedCrowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - mapping(address => uint256) private _balances; + mapping(address => uint256) private _balances; - constructor() internal {} + constructor () internal {} - /** - * @dev Withdraw tokens only after crowdsale ends. - * @param beneficiary Whose tokens will be withdrawn. - */ - function withdrawTokens(address beneficiary) public { - require(hasClosed()); - uint256 amount = _balances[beneficiary]; - require(amount > 0); - _balances[beneficiary] = 0; - _deliverTokens(beneficiary, amount); - } + /** + * @dev Withdraw tokens only after crowdsale ends. + * @param beneficiary Whose tokens will be withdrawn. + */ + function withdrawTokens(address beneficiary) public { + require(hasClosed()); + uint256 amount = _balances[beneficiary]; + require(amount > 0); + _balances[beneficiary] = 0; + _deliverTokens(beneficiary, amount); + } - /** - * @return the balance of an account. - */ - function balanceOf(address account) public view returns(uint256) { - return _balances[account]; - } + /** + * @return the balance of an account. + */ + function balanceOf(address account) public view returns (uint256) { + return _balances[account]; + } - /** - * @dev Overrides parent by storing balances instead of issuing tokens right away. - * @param beneficiary Token purchaser - * @param tokenAmount Amount of tokens purchased - */ - function _processPurchase( - address beneficiary, - uint256 tokenAmount - ) - internal - { - _balances[beneficiary] = _balances[beneficiary].add(tokenAmount); - } + /** + * @dev Overrides parent by storing balances instead of issuing tokens right away. + * @param beneficiary Token purchaser + * @param tokenAmount Amount of tokens purchased + */ + function _processPurchase(address beneficiary, uint256 tokenAmount) internal { + _balances[beneficiary] = _balances[beneficiary].add(tokenAmount); + } } diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index da02baee6..6c5365cc1 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -8,84 +8,83 @@ import "../../payment/escrow/RefundEscrow.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. - * WARNING: note that if you allow tokens to be traded before the goal - * is met, then an attack is possible in which the attacker purchases - * tokens from the crowdsale and when they sees that the goal is + * WARNING: note that if you allow tokens to be traded before the goal + * is met, then an attack is possible in which the attacker purchases + * tokens from the crowdsale and when they sees that the goal is * unlikely to be met, they sell their tokens (possibly at a discount). * The attacker will be refunded when the crowdsale is finalized, and - * the users that purchased from them will be left with worthless + * the users that purchased from them will be left with worthless * tokens. There are many possible ways to avoid this, like making the - * the crowdsale inherit from PostDeliveryCrowdsale, or imposing + * the crowdsale inherit from PostDeliveryCrowdsale, or imposing * restrictions on token trading until the crowdsale is finalized. - * This is being discussed in + * This is being discussed in * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 * This contract will be updated when we agree on a general solution * for this problem. */ contract RefundableCrowdsale is FinalizableCrowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - // minimum amount of funds to be raised in weis - uint256 private _goal; + // minimum amount of funds to be raised in weis + uint256 private _goal; - // refund escrow used to hold funds while crowdsale is running - RefundEscrow private _escrow; + // refund escrow used to hold funds while crowdsale is running + RefundEscrow private _escrow; - /** - * @dev Constructor, creates RefundEscrow. - * @param goal Funding goal - */ - constructor(uint256 goal) internal { - require(goal > 0); - _escrow = new RefundEscrow(wallet()); - _goal = goal; - } - - /** - * @return minimum amount of funds to be raised in wei. - */ - function goal() public view returns(uint256) { - return _goal; - } - - /** - * @dev Investors can claim refunds here if crowdsale is unsuccessful - * @param refundee Whose refund will be claimed. - */ - function claimRefund(address refundee) public { - require(finalized()); - require(!goalReached()); - - _escrow.withdraw(refundee); - } - - /** - * @dev Checks whether funding goal was reached. - * @return Whether funding goal was reached - */ - function goalReached() public view returns (bool) { - return weiRaised() >= _goal; - } - - /** - * @dev escrow finalization task, called when finalize() is called - */ - function _finalization() internal { - if (goalReached()) { - _escrow.close(); - _escrow.beneficiaryWithdraw(); - } else { - _escrow.enableRefunds(); + /** + * @dev Constructor, creates RefundEscrow. + * @param goal Funding goal + */ + constructor (uint256 goal) internal { + require(goal > 0); + _escrow = new RefundEscrow(wallet()); + _goal = goal; } - super._finalization(); - } + /** + * @return minimum amount of funds to be raised in wei. + */ + function goal() public view returns (uint256) { + return _goal; + } - /** - * @dev Overrides Crowdsale fund forwarding, sending funds to escrow. - */ - function _forwardFunds() internal { - _escrow.deposit.value(msg.value)(msg.sender); - } + /** + * @dev Investors can claim refunds here if crowdsale is unsuccessful + * @param refundee Whose refund will be claimed. + */ + function claimRefund(address refundee) public { + require(finalized()); + require(!goalReached()); + _escrow.withdraw(refundee); + } + + /** + * @dev Checks whether funding goal was reached. + * @return Whether funding goal was reached + */ + function goalReached() public view returns (bool) { + return weiRaised() >= _goal; + } + + /** + * @dev escrow finalization task, called when finalize() is called + */ + function _finalization() internal { + if (goalReached()) { + _escrow.close(); + _escrow.beneficiaryWithdraw(); + } else { + _escrow.enableRefunds(); + } + + super._finalization(); + } + + /** + * @dev Overrides Crowdsale fund forwarding, sending funds to escrow. + */ + function _forwardFunds() internal { + _escrow.deposit.value(msg.value)(msg.sender); + } } diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index 346275c7d..b0c09c744 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -11,49 +11,41 @@ import "../../math/Math.sol"; * @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale. */ contract AllowanceCrowdsale is Crowdsale { - using SafeMath for uint256; - using SafeERC20 for IERC20; + using SafeMath for uint256; + using SafeERC20 for IERC20; - address private _tokenWallet; + address private _tokenWallet; - /** - * @dev Constructor, takes token wallet address. - * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale - */ - constructor(address tokenWallet) internal { - require(tokenWallet != address(0)); - _tokenWallet = tokenWallet; - } + /** + * @dev Constructor, takes token wallet address. + * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale + */ + constructor (address tokenWallet) internal { + require(tokenWallet != address(0)); + _tokenWallet = tokenWallet; + } - /** - * @return the address of the wallet that will hold the tokens. - */ - function tokenWallet() public view returns(address) { - return _tokenWallet; - } + /** + * @return the address of the wallet that will hold the tokens. + */ + function tokenWallet() public view returns (address) { + return _tokenWallet; + } - /** - * @dev Checks the amount of tokens left in the allowance. - * @return Amount of tokens left in the allowance - */ - function remainingTokens() public view returns (uint256) { - return Math.min( - token().balanceOf(_tokenWallet), - token().allowance(_tokenWallet, this) - ); - } + /** + * @dev Checks the amount of tokens left in the allowance. + * @return Amount of tokens left in the allowance + */ + function remainingTokens() public view returns (uint256) { + return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, this)); + } - /** - * @dev Overrides parent behavior by transferring tokens from wallet. - * @param beneficiary Token purchaser - * @param tokenAmount Amount of tokens purchased - */ - function _deliverTokens( - address beneficiary, - uint256 tokenAmount - ) - internal - { - token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount); - } + /** + * @dev Overrides parent behavior by transferring tokens from wallet. + * @param beneficiary Token purchaser + * @param tokenAmount Amount of tokens purchased + */ + function _deliverTokens(address beneficiary, uint256 tokenAmount) internal { + token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount); + } } diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index 3ebea857d..1f346a819 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -9,21 +9,15 @@ import "../../token/ERC20/ERC20Mintable.sol"; * Token ownership should be transferred to MintedCrowdsale for minting. */ contract MintedCrowdsale is Crowdsale { - constructor() internal {} + constructor () internal {} - /** - * @dev Overrides delivery by minting tokens upon purchase. - * @param beneficiary Token purchaser - * @param tokenAmount Number of tokens to be minted - */ - function _deliverTokens( - address beneficiary, - uint256 tokenAmount - ) - internal - { - // Potentially dangerous assumption about the type of the token. - require( - ERC20Mintable(address(token())).mint(beneficiary, tokenAmount)); - } + /** + * @dev Overrides delivery by minting tokens upon purchase. + * @param beneficiary Token purchaser + * @param tokenAmount Number of tokens to be minted + */ + function _deliverTokens(address beneficiary, uint256 tokenAmount) internal { + // Potentially dangerous assumption about the type of the token. + require(ERC20Mintable(address(token())).mint(beneficiary, tokenAmount)); + } } diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index c86353c0f..5ac7731a5 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -10,72 +10,69 @@ import "../../math/SafeMath.sol"; * the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate. */ contract IncreasingPriceCrowdsale is TimedCrowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - uint256 private _initialRate; - uint256 private _finalRate; + uint256 private _initialRate; + uint256 private _finalRate; - /** - * @dev Constructor, takes initial and final rates of tokens received per wei contributed. - * @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale - * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale - */ - constructor(uint256 initialRate, uint256 finalRate) internal { - require(finalRate > 0); - require(initialRate > finalRate); - _initialRate = initialRate; - _finalRate = finalRate; - } - - /** - * The base rate function is overridden to revert, since this crowdsale doens't use it, and - * all calls to it are a mistake. - */ - function rate() public view returns(uint256) { - revert(); - } - - /** - * @return the initial rate of the crowdsale. - */ - function initialRate() public view returns(uint256) { - return _initialRate; - } - - /** - * @return the final rate of the crowdsale. - */ - function finalRate() public view returns (uint256) { - return _finalRate; - } - - /** - * @dev Returns the rate of tokens per wei at the present time. - * Note that, as price _increases_ with time, the rate _decreases_. - * @return The number of tokens a buyer gets per wei at a given time - */ - function getCurrentRate() public view returns (uint256) { - if (!isOpen()) { - return 0; + /** + * @dev Constructor, takes initial and final rates of tokens received per wei contributed. + * @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale + * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale + */ + constructor (uint256 initialRate, uint256 finalRate) internal { + require(finalRate > 0); + require(initialRate > finalRate); + _initialRate = initialRate; + _finalRate = finalRate; } - // solium-disable-next-line security/no-block-members - uint256 elapsedTime = block.timestamp.sub(openingTime()); - uint256 timeRange = closingTime().sub(openingTime()); - uint256 rateRange = _initialRate.sub(_finalRate); - return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange)); - } + /** + * The base rate function is overridden to revert, since this crowdsale doens't use it, and + * all calls to it are a mistake. + */ + function rate() public view returns (uint256) { + revert(); + } - /** - * @dev Overrides parent method taking into account variable rate. - * @param weiAmount The value in wei to be converted into tokens - * @return The number of tokens _weiAmount wei will buy at present time - */ - function _getTokenAmount(uint256 weiAmount) - internal view returns (uint256) - { - uint256 currentRate = getCurrentRate(); - return currentRate.mul(weiAmount); - } + /** + * @return the initial rate of the crowdsale. + */ + function initialRate() public view returns (uint256) { + return _initialRate; + } + /** + * @return the final rate of the crowdsale. + */ + function finalRate() public view returns (uint256) { + return _finalRate; + } + + /** + * @dev Returns the rate of tokens per wei at the present time. + * Note that, as price _increases_ with time, the rate _decreases_. + * @return The number of tokens a buyer gets per wei at a given time + */ + function getCurrentRate() public view returns (uint256) { + if (!isOpen()) { + return 0; + } + + // solium-disable-next-line security/no-block-members + uint256 elapsedTime = block.timestamp.sub(openingTime()); + uint256 timeRange = closingTime().sub(openingTime()); + uint256 rateRange = _initialRate.sub(_finalRate); + return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange)); + } + + /** + * @dev Overrides parent method taking into account variable rate. + * @param weiAmount The value in wei to be converted into tokens + * @return The number of tokens _weiAmount wei will buy at present time + */ + function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) { + uint256 currentRate = getCurrentRate(); + return currentRate.mul(weiAmount); + } } diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 4d9eb604d..2b49362c2 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -8,48 +8,41 @@ import "../Crowdsale.sol"; * @dev Crowdsale with a limit for total contributions. */ contract CappedCrowdsale is Crowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - uint256 private _cap; + uint256 private _cap; - /** - * @dev Constructor, takes maximum amount of wei accepted in the crowdsale. - * @param cap Max amount of wei to be contributed - */ - constructor(uint256 cap) internal { - require(cap > 0); - _cap = cap; - } + /** + * @dev Constructor, takes maximum amount of wei accepted in the crowdsale. + * @param cap Max amount of wei to be contributed + */ + constructor (uint256 cap) internal { + require(cap > 0); + _cap = cap; + } - /** - * @return the cap of the crowdsale. - */ - function cap() public view returns(uint256) { - return _cap; - } + /** + * @return the cap of the crowdsale. + */ + function cap() public view returns (uint256) { + return _cap; + } - /** - * @dev Checks whether the cap has been reached. - * @return Whether the cap was reached - */ - function capReached() public view returns (bool) { - return weiRaised() >= _cap; - } - - /** - * @dev Extend parent behavior requiring purchase to respect the funding cap. - * @param beneficiary Token purchaser - * @param weiAmount Amount of wei contributed - */ - function _preValidatePurchase( - address beneficiary, - uint256 weiAmount - ) - internal - view - { - super._preValidatePurchase(beneficiary, weiAmount); - require(weiRaised().add(weiAmount) <= _cap); - } + /** + * @dev Checks whether the cap has been reached. + * @return Whether the cap was reached + */ + function capReached() public view returns (bool) { + return weiRaised() >= _cap; + } + /** + * @dev Extend parent behavior requiring purchase to respect the funding cap. + * @param beneficiary Token purchaser + * @param weiAmount Amount of wei contributed + */ + function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { + super._preValidatePurchase(beneficiary, weiAmount); + require(weiRaised().add(weiAmount) <= _cap); + } } diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index 5a5d4e317..1bae0f96b 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -9,73 +9,57 @@ import "../../access/roles/CapperRole.sol"; * @dev Crowdsale with per-beneficiary caps. */ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { - using SafeMath for uint256; + using SafeMath for uint256; - mapping(address => uint256) private _contributions; - mapping(address => uint256) private _caps; + mapping(address => uint256) private _contributions; + mapping(address => uint256) private _caps; - constructor() internal {} + constructor () internal {} - /** - * @dev Sets a specific beneficiary's maximum contribution. - * @param beneficiary Address to be capped - * @param cap Wei limit for individual contribution - */ - function setCap(address beneficiary, uint256 cap) external onlyCapper { - _caps[beneficiary] = cap; - } + /** + * @dev Sets a specific beneficiary's maximum contribution. + * @param beneficiary Address to be capped + * @param cap Wei limit for individual contribution + */ + function setCap(address beneficiary, uint256 cap) external onlyCapper { + _caps[beneficiary] = cap; + } - /** - * @dev Returns the cap of a specific beneficiary. - * @param beneficiary Address whose cap is to be checked - * @return Current cap for individual beneficiary - */ - function getCap(address beneficiary) public view returns (uint256) { - return _caps[beneficiary]; - } + /** + * @dev Returns the cap of a specific beneficiary. + * @param beneficiary Address whose cap is to be checked + * @return Current cap for individual beneficiary + */ + function getCap(address beneficiary) public view returns (uint256) { + return _caps[beneficiary]; + } - /** - * @dev Returns the amount contributed so far by a specific beneficiary. - * @param beneficiary Address of contributor - * @return Beneficiary contribution so far - */ - function getContribution(address beneficiary) - public view returns (uint256) - { - return _contributions[beneficiary]; - } + /** + * @dev Returns the amount contributed so far by a specific beneficiary. + * @param beneficiary Address of contributor + * @return Beneficiary contribution so far + */ + function getContribution(address beneficiary) public view returns (uint256) { + return _contributions[beneficiary]; + } - /** - * @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap. - * @param beneficiary Token purchaser - * @param weiAmount Amount of wei contributed - */ - function _preValidatePurchase( - address beneficiary, - uint256 weiAmount - ) - internal - view - { - super._preValidatePurchase(beneficiary, weiAmount); - require( - _contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]); - } - - /** - * @dev Extend parent behavior to update beneficiary contributions - * @param beneficiary Token purchaser - * @param weiAmount Amount of wei contributed - */ - function _updatePurchasingState( - address beneficiary, - uint256 weiAmount - ) - internal - { - super._updatePurchasingState(beneficiary, weiAmount); - _contributions[beneficiary] = _contributions[beneficiary].add( - weiAmount); - } + /** + * @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap. + * @param beneficiary Token purchaser + * @param weiAmount Amount of wei contributed + */ + function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view { + super._preValidatePurchase(beneficiary, weiAmount); + require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]); + } + /** + * @dev Extend parent behavior to update beneficiary contributions + * @param beneficiary Token purchaser + * @param weiAmount Amount of wei contributed + */ + function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal { + super._updatePurchasingState(beneficiary, weiAmount); + _contributions[beneficiary] = _contributions[beneficiary].add(weiAmount); + } } diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index 73d6a5c0f..244220034 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -8,78 +8,70 @@ import "../Crowdsale.sol"; * @dev Crowdsale accepting contributions only within a time frame. */ contract TimedCrowdsale is Crowdsale { - using SafeMath for uint256; + using SafeMath for uint256; - uint256 private _openingTime; - uint256 private _closingTime; + uint256 private _openingTime; + uint256 private _closingTime; - /** - * @dev Reverts if not in crowdsale time range. - */ - modifier onlyWhileOpen { - require(isOpen()); - _; - } + /** + * @dev Reverts if not in crowdsale time range. + */ + modifier onlyWhileOpen { + require(isOpen()); + _; + } - /** - * @dev Constructor, takes crowdsale opening and closing times. - * @param openingTime Crowdsale opening time - * @param closingTime Crowdsale closing time - */ - constructor(uint256 openingTime, uint256 closingTime) internal { - // solium-disable-next-line security/no-block-members - require(openingTime >= block.timestamp); - require(closingTime > openingTime); + /** + * @dev Constructor, takes crowdsale opening and closing times. + * @param openingTime Crowdsale opening time + * @param closingTime Crowdsale closing time + */ + constructor (uint256 openingTime, uint256 closingTime) internal { + // solium-disable-next-line security/no-block-members + require(openingTime >= block.timestamp); + require(closingTime > openingTime); - _openingTime = openingTime; - _closingTime = closingTime; - } + _openingTime = openingTime; + _closingTime = closingTime; + } - /** - * @return the crowdsale opening time. - */ - function openingTime() public view returns(uint256) { - return _openingTime; - } + /** + * @return the crowdsale opening time. + */ + function openingTime() public view returns (uint256) { + return _openingTime; + } - /** - * @return the crowdsale closing time. - */ - function closingTime() public view returns(uint256) { - return _closingTime; - } + /** + * @return the crowdsale closing time. + */ + function closingTime() public view returns (uint256) { + return _closingTime; + } - /** - * @return true if the crowdsale is open, false otherwise. - */ - function isOpen() public view returns (bool) { - // solium-disable-next-line security/no-block-members - return block.timestamp >= _openingTime && block.timestamp <= _closingTime; - } + /** + * @return true if the crowdsale is open, false otherwise. + */ + function isOpen() public view returns (bool) { + // solium-disable-next-line security/no-block-members + return block.timestamp >= _openingTime && block.timestamp <= _closingTime; + } - /** - * @dev Checks whether the period in which the crowdsale is open has already elapsed. - * @return Whether crowdsale period has elapsed - */ - function hasClosed() public view returns (bool) { - // solium-disable-next-line security/no-block-members - return block.timestamp > _closingTime; - } - - /** - * @dev Extend parent behavior requiring to be within contributing period - * @param beneficiary Token purchaser - * @param weiAmount Amount of wei contributed - */ - function _preValidatePurchase( - address beneficiary, - uint256 weiAmount - ) - internal - onlyWhileOpen - view - { - super._preValidatePurchase(beneficiary, weiAmount); - } + /** + * @dev Checks whether the period in which the crowdsale is open has already elapsed. + * @return Whether crowdsale period has elapsed + */ + function hasClosed() public view returns (bool) { + // solium-disable-next-line security/no-block-members + return block.timestamp > _closingTime; + } + /** + * @dev Extend parent behavior requiring to be within contributing period + * @param beneficiary Token purchaser + * @param weiAmount Amount of wei contributed + */ + function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal onlyWhileOpen view { + super._preValidatePurchase(beneficiary, weiAmount); + } } diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 71c0e41ed..4c91663ec 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -8,64 +8,53 @@ pragma solidity ^0.4.24; */ library ECDSA { + /** + * @dev Recover signer address from a message by using their signature + * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. + * @param signature bytes signature, the signature is generated using web3.eth.sign() + */ + function recover(bytes32 hash, bytes signature) internal pure returns (address) { + bytes32 r; + bytes32 s; + uint8 v; - /** - * @dev Recover signer address from a message by using their signature - * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. - * @param signature bytes signature, the signature is generated using web3.eth.sign() - */ - function recover(bytes32 hash, bytes signature) - internal - pure - returns (address) - { - bytes32 r; - bytes32 s; - uint8 v; + // Check the signature length + if (signature.length != 65) { + return (address(0)); + } - // Check the signature length - if (signature.length != 65) { - return (address(0)); + // Divide the signature in r, s and v variables + // ecrecover takes the signature parameters, and the only way to get them + // currently is to use assembly. + // solium-disable-next-line security/no-inline-assembly + assembly { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) + } + + // 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 { + // solium-disable-next-line arg-overflow + return ecrecover(hash, v, r, s); + } } - // Divide the signature in r, s and v variables - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solium-disable-next-line security/no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) + /** + * toEthSignedMessageHash + * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" + * and hash the result + */ + function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { + // 32 is the length in bytes of hash, + // enforced by the type signature above + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } - - // 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 { - // solium-disable-next-line arg-overflow - return ecrecover(hash, v, r, s); - } - } - - /** - * toEthSignedMessageHash - * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" - * and hash the result - */ - function toEthSignedMessageHash(bytes32 hash) - internal - pure - returns (bytes32) - { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) - ); - } } diff --git a/contracts/cryptography/MerkleProof.sol b/contracts/cryptography/MerkleProof.sol index a0c304c57..31e469367 100644 --- a/contracts/cryptography/MerkleProof.sol +++ b/contracts/cryptography/MerkleProof.sol @@ -6,37 +6,29 @@ pragma solidity ^0.4.24; * https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol */ library MerkleProof { - /** - * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves - * and each pair of pre-images are sorted. - * @param proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree - * @param root Merkle root - * @param leaf Leaf of Merkle tree - */ - function verify( - bytes32[] proof, - bytes32 root, - bytes32 leaf - ) - internal - pure - returns (bool) - { - bytes32 computedHash = leaf; + /** + * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves + * and each pair of pre-images are sorted. + * @param proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree + * @param root Merkle root + * @param leaf Leaf of Merkle tree + */ + function verify(bytes32[] proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { + bytes32 computedHash = leaf; - for (uint256 i = 0; i < proof.length; i++) { - bytes32 proofElement = proof[i]; + for (uint256 i = 0; i < proof.length; i++) { + bytes32 proofElement = proof[i]; - if (computedHash < proofElement) { - // Hash(current computed hash + current element of the proof) - computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); - } else { - // Hash(current element of the proof + current computed hash) - computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); - } + if (computedHash < proofElement) { + // Hash(current computed hash + current element of the proof) + computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); + } else { + // Hash(current element of the proof + current computed hash) + computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); + } + } + + // Check if the computed hash (root) is equal to the provided root + return computedHash == root; } - - // Check if the computed hash (root) is equal to the provided root - return computedHash == root; - } } diff --git a/contracts/drafts/Counter.sol b/contracts/drafts/Counter.sol index 3557bd744..12bcf0848 100644 --- a/contracts/drafts/Counter.sol +++ b/contracts/drafts/Counter.sol @@ -13,16 +13,12 @@ pragma solidity ^0.4.24; * so it's not something you have to worry about.) */ library Counter { + struct Counter { + uint256 current; // default: 0 + } - struct Counter { - uint256 current; // default: 0 - } - - function next(Counter storage index) - internal - returns (uint256) - { - index.current += 1; - return index.current; - } + function next(Counter storage index) internal returns (uint256) { + index.current += 1; + return index.current; + } } diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index 9057711d9..460887221 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -9,19 +9,17 @@ import "../../token/ERC20/IERC20.sol"; * @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/IERC721.sol#L17 when 1046 is finalized */ contract ERC20TokenMetadata is IERC20 { - function tokenURI() external view returns (string); + function tokenURI() external view returns (string); } contract ERC20WithMetadata is ERC20TokenMetadata { - string private _tokenURI; + string private _tokenURI; - constructor(string tokenURI) - public - { - _tokenURI = tokenURI; - } + constructor (string tokenURI) public { + _tokenURI = tokenURI; + } - function tokenURI() external view returns (string) { - return _tokenURI; - } + function tokenURI() external view returns (string) { + return _tokenURI; + } } diff --git a/contracts/drafts/ERC20Migrator.sol b/contracts/drafts/ERC20Migrator.sol index 44ed16423..83a0401ff 100644 --- a/contracts/drafts/ERC20Migrator.sol +++ b/contracts/drafts/ERC20Migrator.sol @@ -32,69 +32,69 @@ import "../math/Math.sol"; * ``` */ contract ERC20Migrator { - using SafeERC20 for IERC20; + using SafeERC20 for IERC20; - /// Address of the old token contract - IERC20 private _legacyToken; + /// Address of the old token contract + IERC20 private _legacyToken; - /// Address of the new token contract - ERC20Mintable private _newToken; + /// Address of the new token contract + ERC20Mintable private _newToken; - /** - * @param legacyToken address of the old token contract - */ - constructor(IERC20 legacyToken) public { - require(legacyToken != address(0)); - _legacyToken = legacyToken; - } + /** + * @param legacyToken address of the old token contract + */ + constructor (IERC20 legacyToken) public { + require(legacyToken != address(0)); + _legacyToken = legacyToken; + } - /** - * @dev Returns the legacy token that is being migrated. - */ - function legacyToken() public view returns (IERC20) { - return _legacyToken; - } + /** + * @dev Returns the legacy token that is being migrated. + */ + function legacyToken() public view returns (IERC20) { + return _legacyToken; + } - /** - * @dev Returns the new token to which we are migrating. - */ - function newToken() public view returns (IERC20) { - return _newToken; - } + /** + * @dev Returns the new token to which we are migrating. + */ + function newToken() public view returns (IERC20) { + return _newToken; + } - /** - * @dev Begins the migration by setting which is the new token that will be - * minted. This contract must be a minter for the new token. - * @param newToken the token that will be minted - */ - function beginMigration(ERC20Mintable newToken) public { - require(_newToken == address(0)); - require(newToken != address(0)); - require(newToken.isMinter(this)); + /** + * @dev Begins the migration by setting which is the new token that will be + * minted. This contract must be a minter for the new token. + * @param newToken the token that will be minted + */ + function beginMigration(ERC20Mintable newToken) public { + require(_newToken == address(0)); + require(newToken != address(0)); + require(newToken.isMinter(this)); - _newToken = newToken; - } + _newToken = newToken; + } - /** - * @dev Transfers part of an account's balance in the old token to this - * contract, and mints the same amount of new tokens for that account. - * @param account whose tokens will be migrated - * @param amount amount of tokens to be migrated - */ - function migrate(address account, uint256 amount) public { - _legacyToken.safeTransferFrom(account, this, amount); - _newToken.mint(account, amount); - } + /** + * @dev Transfers part of an account's balance in the old token to this + * contract, and mints the same amount of new tokens for that account. + * @param account whose tokens will be migrated + * @param amount amount of tokens to be migrated + */ + function migrate(address account, uint256 amount) public { + _legacyToken.safeTransferFrom(account, this, amount); + _newToken.mint(account, amount); + } - /** - * @dev Transfers all of an account's allowed balance in the old token to - * this contract, and mints the same amount of new tokens for that account. - * @param account whose tokens will be migrated - */ - function migrateAll(address account) public { - uint256 balance = _legacyToken.balanceOf(account); - uint256 allowance = _legacyToken.allowance(account, this); - uint256 amount = Math.min(balance, allowance); - migrate(account, amount); - } + /** + * @dev Transfers all of an account's allowed balance in the old token to + * this contract, and mints the same amount of new tokens for that account. + * @param account whose tokens will be migrated + */ + function migrateAll(address account) public { + uint256 balance = _legacyToken.balanceOf(account); + uint256 allowance = _legacyToken.allowance(account, this); + uint256 amount = Math.min(balance, allowance); + migrate(account, amount); + } } diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index 2cd600b35..e0e33fcff 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -35,112 +35,84 @@ import "../cryptography/ECDSA.sol"; * See https://ethereum.stackexchange.com/a/50616 for more details. */ contract SignatureBouncer is SignerRole { - using ECDSA for bytes32; + using ECDSA for bytes32; - // Function selectors are 4 bytes long, as documented in - // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector - uint256 private constant _METHOD_ID_SIZE = 4; - // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes - uint256 private constant _SIGNATURE_SIZE = 96; + // Function selectors are 4 bytes long, as documented in + // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector + uint256 private constant _METHOD_ID_SIZE = 4; + // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes + uint256 private constant _SIGNATURE_SIZE = 96; - constructor() internal {} + constructor () internal {} - /** - * @dev requires that a valid signature of a signer was provided - */ - modifier onlyValidSignature(bytes signature) - { - require(_isValidSignature(msg.sender, signature)); - _; - } - - /** - * @dev requires that a valid signature with a specifed method of a signer was provided - */ - modifier onlyValidSignatureAndMethod(bytes signature) - { - require(_isValidSignatureAndMethod(msg.sender, signature)); - _; - } - - /** - * @dev requires that a valid signature with a specifed method and params of a signer was provided - */ - modifier onlyValidSignatureAndData(bytes signature) - { - require(_isValidSignatureAndData(msg.sender, signature)); - _; - } - - /** - * @dev is the signature of `this + sender` from a signer? - * @return bool - */ - function _isValidSignature(address account, bytes signature) - internal - view - returns (bool) - { - return _isValidDataHash( - keccak256(abi.encodePacked(address(this), account)), - signature - ); - } - - /** - * @dev is the signature of `this + sender + methodId` from a signer? - * @return bool - */ - function _isValidSignatureAndMethod(address account, bytes signature) - internal - view - returns (bool) - { - bytes memory data = new bytes(_METHOD_ID_SIZE); - for (uint i = 0; i < data.length; i++) { - data[i] = msg.data[i]; + /** + * @dev requires that a valid signature of a signer was provided + */ + modifier onlyValidSignature(bytes signature) { + require(_isValidSignature(msg.sender, signature)); + _; } - return _isValidDataHash( - keccak256(abi.encodePacked(address(this), account, data)), - signature - ); - } - /** - * @dev is the signature of `this + sender + methodId + params(s)` from a signer? - * @notice the signature parameter of the method being validated must be the "last" parameter - * @return bool - */ - function _isValidSignatureAndData(address account, bytes signature) - internal - view - returns (bool) - { - require(msg.data.length > _SIGNATURE_SIZE); - bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); - for (uint i = 0; i < data.length; i++) { - data[i] = msg.data[i]; + /** + * @dev requires that a valid signature with a specifed method of a signer was provided + */ + modifier onlyValidSignatureAndMethod(bytes signature) { + require(_isValidSignatureAndMethod(msg.sender, signature)); + _; } - return _isValidDataHash( - keccak256(abi.encodePacked(address(this), account, data)), - signature - ); - } - /** - * @dev internal function to convert a hash to an eth signed message - * and then recover the signature and check it against the signer role - * @return bool - */ - function _isValidDataHash(bytes32 hash, bytes signature) - internal - view - returns (bool) - { - address signer = hash - .toEthSignedMessageHash() - .recover(signature); + /** + * @dev requires that a valid signature with a specifed method and params of a signer was provided + */ + modifier onlyValidSignatureAndData(bytes signature) { + require(_isValidSignatureAndData(msg.sender, signature)); + _; + } - return signer != address(0) && isSigner(signer); - } + /** + * @dev is the signature of `this + sender` from a signer? + * @return bool + */ + function _isValidSignature(address account, bytes signature) internal view returns (bool) { + return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature); + } + + /** + * @dev is the signature of `this + sender + methodId` from a signer? + * @return bool + */ + function _isValidSignatureAndMethod(address account, bytes signature) internal view returns (bool) { + bytes memory data = new bytes(_METHOD_ID_SIZE); + for (uint i = 0; i < data.length; i++) { + data[i] = msg.data[i]; + } + return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); + } + + /** + * @dev is the signature of `this + sender + methodId + params(s)` from a signer? + * @notice the signature parameter of the method being validated must be the "last" parameter + * @return bool + */ + function _isValidSignatureAndData(address account, bytes signature) internal view returns (bool) { + require(msg.data.length > _SIGNATURE_SIZE); + + bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); + for (uint i = 0; i < data.length; i++) { + data[i] = msg.data[i]; + } + + return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); + } + + /** + * @dev internal function to convert a hash to an eth signed message + * and then recover the signature and check it against the signer role + * @return bool + */ + function _isValidDataHash(bytes32 hash, bytes signature) internal view returns (bool) { + address signer = hash.toEthSignedMessageHash().recover(signature); + + return signer != address(0) && isSigner(signer); + } } diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 3fa49f79f..d8ea749e1 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -13,163 +13,155 @@ import "../math/SafeMath.sol"; * owner. */ contract TokenVesting is Ownable { - using SafeMath for uint256; - using SafeERC20 for IERC20; + using SafeMath for uint256; + using SafeERC20 for IERC20; - event TokensReleased(address token, uint256 amount); - event TokenVestingRevoked(address token); + event TokensReleased(address token, uint256 amount); + event TokenVestingRevoked(address token); - // beneficiary of tokens after they are released - address private _beneficiary; + // beneficiary of tokens after they are released + address private _beneficiary; - uint256 private _cliff; - uint256 private _start; - uint256 private _duration; + uint256 private _cliff; + uint256 private _start; + uint256 private _duration; - bool private _revocable; + bool private _revocable; - mapping (address => uint256) private _released; - mapping (address => bool) private _revoked; + mapping (address => uint256) private _released; + mapping (address => bool) private _revoked; - /** - * @dev Creates a vesting contract that vests its balance of any ERC20 token to the - * beneficiary, gradually in a linear fashion until start + duration. By then all - * of the balance will have vested. - * @param beneficiary address of the beneficiary to whom vested tokens are transferred - * @param cliffDuration duration in seconds of the cliff in which tokens will begin to vest - * @param start the time (as Unix time) at which point vesting starts - * @param duration duration in seconds of the period in which the tokens will vest - * @param revocable whether the vesting is revocable or not - */ - constructor( - address beneficiary, - uint256 start, - uint256 cliffDuration, - uint256 duration, - bool revocable - ) - public - { - require(beneficiary != address(0)); - require(cliffDuration <= duration); - require(duration > 0); - require(start.add(duration) > block.timestamp); + /** + * @dev Creates a vesting contract that vests its balance of any ERC20 token to the + * beneficiary, gradually in a linear fashion until start + duration. By then all + * of the balance will have vested. + * @param beneficiary address of the beneficiary to whom vested tokens are transferred + * @param cliffDuration duration in seconds of the cliff in which tokens will begin to vest + * @param start the time (as Unix time) at which point vesting starts + * @param duration duration in seconds of the period in which the tokens will vest + * @param revocable whether the vesting is revocable or not + */ + constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public { + require(beneficiary != address(0)); + require(cliffDuration <= duration); + require(duration > 0); + require(start.add(duration) > block.timestamp); - _beneficiary = beneficiary; - _revocable = revocable; - _duration = duration; - _cliff = start.add(cliffDuration); - _start = start; - } - - /** - * @return the beneficiary of the tokens. - */ - function beneficiary() public view returns(address) { - return _beneficiary; - } - - /** - * @return the cliff time of the token vesting. - */ - function cliff() public view returns(uint256) { - return _cliff; - } - - /** - * @return the start time of the token vesting. - */ - function start() public view returns(uint256) { - return _start; - } - - /** - * @return the duration of the token vesting. - */ - function duration() public view returns(uint256) { - return _duration; - } - - /** - * @return true if the vesting is revocable. - */ - function revocable() public view returns(bool) { - return _revocable; - } - - /** - * @return the amount of the token released. - */ - function released(address token) public view returns(uint256) { - return _released[token]; - } - - /** - * @return true if the token is revoked. - */ - function revoked(address token) public view returns(bool) { - return _revoked[token]; - } - - /** - * @notice Transfers vested tokens to beneficiary. - * @param token ERC20 token which is being vested - */ - function release(IERC20 token) public { - uint256 unreleased = _releasableAmount(token); - - require(unreleased > 0); - - _released[token] = _released[token].add(unreleased); - - token.safeTransfer(_beneficiary, unreleased); - - emit TokensReleased(token, unreleased); - } - - /** - * @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(IERC20 token) public onlyOwner { - require(_revocable); - require(!_revoked[token]); - - uint256 balance = token.balanceOf(address(this)); - - uint256 unreleased = _releasableAmount(token); - uint256 refund = balance.sub(unreleased); - - _revoked[token] = true; - - token.safeTransfer(owner(), refund); - - emit TokenVestingRevoked(token); - } - - /** - * @dev Calculates the amount that has already vested but hasn't been released yet. - * @param token ERC20 token which is being vested - */ - function _releasableAmount(IERC20 token) private view 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(IERC20 token) private view returns (uint256) { - uint256 currentBalance = token.balanceOf(address(this)); - uint256 totalBalance = currentBalance.add(_released[token]); - - if (block.timestamp < _cliff) { - return 0; - } else if (block.timestamp >= _start.add(_duration) || _revoked[token]) { - return totalBalance; - } else { - return totalBalance.mul(block.timestamp.sub(_start)).div(_duration); + _beneficiary = beneficiary; + _revocable = revocable; + _duration = duration; + _cliff = start.add(cliffDuration); + _start = start; + } + + /** + * @return the beneficiary of the tokens. + */ + function beneficiary() public view returns (address) { + return _beneficiary; + } + + /** + * @return the cliff time of the token vesting. + */ + function cliff() public view returns (uint256) { + return _cliff; + } + + /** + * @return the start time of the token vesting. + */ + function start() public view returns (uint256) { + return _start; + } + + /** + * @return the duration of the token vesting. + */ + function duration() public view returns (uint256) { + return _duration; + } + + /** + * @return true if the vesting is revocable. + */ + function revocable() public view returns (bool) { + return _revocable; + } + + /** + * @return the amount of the token released. + */ + function released(address token) public view returns (uint256) { + return _released[token]; + } + + /** + * @return true if the token is revoked. + */ + function revoked(address token) public view returns (bool) { + return _revoked[token]; + } + + /** + * @notice Transfers vested tokens to beneficiary. + * @param token ERC20 token which is being vested + */ + function release(IERC20 token) public { + uint256 unreleased = _releasableAmount(token); + + require(unreleased > 0); + + _released[token] = _released[token].add(unreleased); + + token.safeTransfer(_beneficiary, unreleased); + + emit TokensReleased(token, unreleased); + } + + /** + * @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(IERC20 token) public onlyOwner { + require(_revocable); + require(!_revoked[token]); + + uint256 balance = token.balanceOf(address(this)); + + uint256 unreleased = _releasableAmount(token); + uint256 refund = balance.sub(unreleased); + + _revoked[token] = true; + + token.safeTransfer(owner(), refund); + + emit TokenVestingRevoked(token); + } + + /** + * @dev Calculates the amount that has already vested but hasn't been released yet. + * @param token ERC20 token which is being vested + */ + function _releasableAmount(IERC20 token) private view 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(IERC20 token) private view returns (uint256) { + uint256 currentBalance = token.balanceOf(address(this)); + uint256 totalBalance = currentBalance.add(_released[token]); + + if (block.timestamp < _cliff) { + return 0; + } else if (block.timestamp >= _start.add(_duration) || _revoked[token]) { + return totalBalance; + } else { + return totalBalance.mul(block.timestamp.sub(_start)).div(_duration); + } } - } } diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index d22598092..45bf24b11 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -12,7 +12,7 @@ import "../token/ERC20/ERC20Detailed.sol"; * It is meant to be used in a crowdsale contract. */ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { - constructor() public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {} + constructor () public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {} } /** @@ -34,24 +34,23 @@ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { // --elopio - 2018-05-10 // solium-disable-next-line max-len contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale { - - constructor( - uint256 openingTime, - uint256 closingTime, - uint256 rate, - address wallet, - uint256 cap, - ERC20Mintable token, - uint256 goal - ) - public - Crowdsale(rate, wallet, token) - CappedCrowdsale(cap) - TimedCrowdsale(openingTime, closingTime) - RefundableCrowdsale(goal) - { - //As goal needs to be met for a successful crowdsale - //the value needs to less or equal than a cap which is limit for accepted funds - require(goal <= cap); - } + constructor ( + uint256 openingTime, + uint256 closingTime, + uint256 rate, + address wallet, + uint256 cap, + ERC20Mintable token, + uint256 goal + ) + public + Crowdsale(rate, wallet, token) + CappedCrowdsale(cap) + TimedCrowdsale(openingTime, closingTime) + RefundableCrowdsale(goal) + { + //As goal needs to be met for a successful crowdsale + //the value needs to less or equal than a cap which is limit for accepted funds + require(goal <= cap); + } } diff --git a/contracts/examples/SimpleToken.sol b/contracts/examples/SimpleToken.sol index 04b016a73..95b31ea37 100644 --- a/contracts/examples/SimpleToken.sol +++ b/contracts/examples/SimpleToken.sol @@ -10,14 +10,12 @@ import "../token/ERC20/ERC20Detailed.sol"; * `ERC20` functions. */ contract SimpleToken is ERC20, ERC20Detailed { + uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals())); - uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals())); - - /** - * @dev Constructor that gives msg.sender all of existing tokens. - */ - constructor() public ERC20Detailed("SimpleToken", "SIM", 18) { - _mint(msg.sender, INITIAL_SUPPLY); - } - + /** + * @dev Constructor that gives msg.sender all of existing tokens. + */ + constructor () public ERC20Detailed("SimpleToken", "SIM", 18) { + _mint(msg.sender, INITIAL_SUPPLY); + } } diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 5d083acdf..f1dfbcff1 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -8,46 +8,37 @@ import "./IERC165.sol"; * @dev Implements ERC165 using a lookup table. */ contract ERC165 is IERC165 { + bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; + /** + * 0x01ffc9a7 === + * bytes4(keccak256('supportsInterface(bytes4)')) + */ - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ + /** + * @dev a mapping of interface id to whether or not it's supported + */ + mapping(bytes4 => bool) private _supportedInterfaces; - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; + /** + * @dev A contract implementing SupportsInterfaceWithLookup + * implement ERC165 itself + */ + constructor () internal { + _registerInterface(_InterfaceId_ERC165); + } - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() - internal - { - _registerInterface(_InterfaceId_ERC165); - } + /** + * @dev implement supportsInterface(bytes4) using a lookup table + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool) { + return _supportedInterfaces[interfaceId]; + } - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) - external - view - returns (bool) - { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev internal method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) - internal - { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } + /** + * @dev internal method for registering an interface + */ + function _registerInterface(bytes4 interfaceId) internal { + require(interfaceId != 0xffffffff); + _supportedInterfaces[interfaceId] = true; + } } diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 2490b191e..e40db319e 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -6,141 +6,118 @@ pragma solidity ^0.4.24; * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md */ library ERC165Checker { - // As per the EIP-165 spec, no interface should ever match 0xffffffff - bytes4 private constant _InterfaceId_Invalid = 0xffffffff; + // As per the EIP-165 spec, no interface should ever match 0xffffffff + bytes4 private constant _InterfaceId_Invalid = 0xffffffff; - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ + bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; + /** + * 0x01ffc9a7 === + * bytes4(keccak256('supportsInterface(bytes4)')) + */ - /** - * @notice Query if a contract supports ERC165 - * @param account The address of the contract to query for support of ERC165 - * @return true if the contract at account implements ERC165 - */ - function _supportsERC165(address account) - internal - view - returns (bool) - { - // Any contract that implements ERC165 must explicitly indicate support of - // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return _supportsERC165Interface(account, _InterfaceId_ERC165) && - !_supportsERC165Interface(account, _InterfaceId_Invalid); - } - - /** - * @notice Query if a contract implements an interface, also checks support of ERC165 - * @param account The address of the contract to query for support of an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @return true if the contract at account indicates support of the interface with - * identifier interfaceId, false otherwise - * @dev Interface identification is specified in ERC-165. - */ - function _supportsInterface(address account, bytes4 interfaceId) - internal - view - returns (bool) - { - // query support of both ERC165 as per the spec and support of _interfaceId - return _supportsERC165(account) && - _supportsERC165Interface(account, interfaceId); - } - - /** - * @notice Query if a contract implements interfaces, also checks support of ERC165 - * @param account The address of the contract to query for support of an interface - * @param interfaceIds A list of interface identifiers, as specified in ERC-165 - * @return true if the contract at account indicates support all interfaces in the - * interfaceIds list, false otherwise - * @dev Interface identification is specified in ERC-165. - */ - function _supportsAllInterfaces(address account, bytes4[] interfaceIds) - internal - view - returns (bool) - { - // query support of ERC165 itself - if (!_supportsERC165(account)) { - return false; + /** + * @notice Query if a contract supports ERC165 + * @param account The address of the contract to query for support of ERC165 + * @return true if the contract at account implements ERC165 + */ + function _supportsERC165(address account) internal view returns (bool) { + // Any contract that implements ERC165 must explicitly indicate support of + // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid + return _supportsERC165Interface(account, _InterfaceId_ERC165) && + !_supportsERC165Interface(account, _InterfaceId_Invalid); } - // query support of each interface in _interfaceIds - for (uint256 i = 0; i < interfaceIds.length; i++) { - if (!_supportsERC165Interface(account, interfaceIds[i])) { - return false; - } + /** + * @notice Query if a contract implements an interface, also checks support of ERC165 + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return true if the contract at account indicates support of the interface with + * identifier interfaceId, false otherwise + * @dev Interface identification is specified in ERC-165. + */ + function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { + // query support of both ERC165 as per the spec and support of _interfaceId + return _supportsERC165(account) && + _supportsERC165Interface(account, interfaceId); } - // all interfaces supported - return true; - } + /** + * @notice Query if a contract implements interfaces, also checks support of ERC165 + * @param account The address of the contract to query for support of an interface + * @param interfaceIds A list of interface identifiers, as specified in ERC-165 + * @return true if the contract at account indicates support all interfaces in the + * interfaceIds list, false otherwise + * @dev Interface identification is specified in ERC-165. + */ + function _supportsAllInterfaces(address account, bytes4[] interfaceIds) internal view returns (bool) { + // query support of ERC165 itself + if (!_supportsERC165(account)) { + return false; + } - /** - * @notice Query if a contract implements an interface, does not check ERC165 support - * @param account The address of the contract to query for support of an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @return true if the contract at account indicates support of the interface with - * identifier interfaceId, false otherwise - * @dev Assumes that account contains a contract that supports ERC165, otherwise - * the behavior of this method is undefined. This precondition can be checked - * with the `supportsERC165` method in this library. - * Interface identification is specified in ERC-165. - */ - function _supportsERC165Interface(address account, bytes4 interfaceId) - private - view - returns (bool) - { - // success determines whether the staticcall succeeded and result determines - // whether the contract at account indicates support of _interfaceId - (bool success, bool result) = _callERC165SupportsInterface( - account, interfaceId); + // query support of each interface in _interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + if (!_supportsERC165Interface(account, interfaceIds[i])) { + return false; + } + } - return (success && result); - } - - /** - * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw - * @param account The address of the contract to query for support of an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @return success true if the STATICCALL succeeded, false otherwise - * @return result true if the STATICCALL succeeded and the contract at account - * indicates support of the interface with identifier interfaceId, false otherwise - */ - function _callERC165SupportsInterface( - address account, - bytes4 interfaceId - ) - private - view - returns (bool success, bool result) - { - bytes memory encodedParams = abi.encodeWithSelector( - _InterfaceId_ERC165, - interfaceId - ); - - // solium-disable-next-line security/no-inline-assembly - assembly { - let encodedParams_data := add(0x20, encodedParams) - let encodedParams_size := mload(encodedParams) - - let output := mload(0x40) // Find empty storage location using "free memory pointer" - mstore(output, 0x0) - - success := staticcall( - 30000, // 30k gas - account, // To addr - encodedParams_data, - encodedParams_size, - output, - 0x20 // Outputs are 32 bytes long - ) - - result := mload(output) // Load the result + // all interfaces supported + return true; + } + + /** + * @notice Query if a contract implements an interface, does not check ERC165 support + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return true if the contract at account indicates support of the interface with + * identifier interfaceId, false otherwise + * @dev Assumes that account contains a contract that supports ERC165, otherwise + * the behavior of this method is undefined. This precondition can be checked + * with the `supportsERC165` method in this library. + * Interface identification is specified in ERC-165. + */ + function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { + // success determines whether the staticcall succeeded and result determines + // whether the contract at account indicates support of _interfaceId + (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); + + return (success && result); + } + + /** + * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return success true if the STATICCALL succeeded, false otherwise + * @return result true if the STATICCALL succeeded and the contract at account + * indicates support of the interface with identifier interfaceId, false otherwise + */ + function _callERC165SupportsInterface(address account, bytes4 interfaceId) + private + view + returns (bool success, bool result) + { + bytes memory encodedParams = abi.encodeWithSelector(_InterfaceId_ERC165,interfaceId); + + // solium-disable-next-line security/no-inline-assembly + assembly { + let encodedParams_data := add(0x20, encodedParams) + let encodedParams_size := mload(encodedParams) + + let output := mload(0x40) // Find empty storage location using "free memory pointer" + mstore(output, 0x0) + + success := staticcall( + 30000, // 30k gas + account, // To addr + encodedParams_data, + encodedParams_size, + output, + 0x20 // Outputs are 32 bytes long + ) + + result := mload(output) // Load the result + } } - } } diff --git a/contracts/introspection/IERC165.sol b/contracts/introspection/IERC165.sol index 4e4b7bbf6..da133b0b4 100644 --- a/contracts/introspection/IERC165.sol +++ b/contracts/introspection/IERC165.sol @@ -5,15 +5,11 @@ pragma solidity ^0.4.24; * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md */ interface IERC165 { - - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) - external - view - returns (bool); + /** + * @notice Query if a contract implements an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @dev Interface identification is specified in ERC-165. This function + * uses less than 30,000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); } diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index 3703fed4b..d74759440 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -7,51 +7,51 @@ import "../access/roles/PauserRole.sol"; * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is PauserRole { - event Paused(address account); - event Unpaused(address account); + event Paused(address account); + event Unpaused(address account); - bool private _paused; + bool private _paused; - constructor() internal { - _paused = false; - } + constructor () internal { + _paused = false; + } - /** - * @return true if the contract is paused, false otherwise. - */ - function paused() public view returns(bool) { - return _paused; - } + /** + * @return true if the contract is paused, false otherwise. + */ + function paused() public view returns (bool) { + return _paused; + } - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!_paused); - _; - } + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!_paused); + _; + } - /** - * @dev Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(_paused); - _; - } + /** + * @dev Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(_paused); + _; + } - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() public onlyPauser whenNotPaused { - _paused = true; - emit Paused(msg.sender); - } + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() public onlyPauser whenNotPaused { + _paused = true; + emit Paused(msg.sender); + } - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() public onlyPauser whenPaused { - _paused = false; - emit Unpaused(msg.sender); - } + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() public onlyPauser whenPaused { + _paused = false; + emit Unpaused(msg.sender); + } } diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index ffff83961..b57f0d3e6 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -5,27 +5,27 @@ pragma solidity ^0.4.24; * @dev Assorted math operations */ library Math { - /** - * @dev Returns the largest of two numbers. - */ - function max(uint256 a, uint256 b) internal pure returns (uint256) { - return a >= b ? a : b; - } + /** + * @dev Returns the largest of two numbers. + */ + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return a >= b ? a : b; + } - /** - * @dev Returns the smallest of two numbers. - */ - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } + /** + * @dev Returns the smallest of two numbers. + */ + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } - /** - * @dev Calculates the average of two numbers. Since these are integers, - * averages of an even and odd number cannot be represented, and will be - * rounded down. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); - } + /** + * @dev Calculates the average of two numbers. Since these are integers, + * averages of an even and odd number cannot be represented, and will be + * rounded down. + */ + function average(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b) / 2 can overflow, so we distribute + return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); + } } diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index 97494e1f1..f42c48e25 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -5,61 +5,61 @@ pragma solidity ^0.4.24; * @dev Math operations with safety checks that revert on error */ library SafeMath { + /** + * @dev Multiplies two numbers, reverts on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } - /** - * @dev Multiplies two numbers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; + uint256 c = a * b; + require(c / a == b); + + return c; } - uint256 c = a * b; - require(c / a == b); + /** + * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return c; - } + return c; + } - /** - * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0); // Solidity only automatically asserts when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold + /** + * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(b <= a); + uint256 c = a - b; - return c; - } + return c; + } - /** - * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; + /** + * @dev Adds two numbers, reverts on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a); - return c; - } + return c; + } - /** - * @dev Adds two numbers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two numbers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } + /** + * @dev Divides two numbers and returns the remainder (unsigned integer modulo), + * reverts when dividing by zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + require(b != 0); + return a % b; + } } diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol index e29396056..b60fe618f 100644 --- a/contracts/mocks/AddressImpl.sol +++ b/contracts/mocks/AddressImpl.sol @@ -3,12 +3,7 @@ pragma solidity ^0.4.24; import "../utils/Address.sol"; contract AddressImpl { - function isContract(address account) - external - view - returns (bool) - { - return Address.isContract(account); - } - + function isContract(address account) external view returns (bool) { + return Address.isContract(account); + } } diff --git a/contracts/mocks/AllowanceCrowdsaleImpl.sol b/contracts/mocks/AllowanceCrowdsaleImpl.sol index 5b2104e38..67e94fd48 100644 --- a/contracts/mocks/AllowanceCrowdsaleImpl.sol +++ b/contracts/mocks/AllowanceCrowdsaleImpl.sol @@ -4,17 +4,9 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/emission/AllowanceCrowdsale.sol"; contract AllowanceCrowdsaleImpl is AllowanceCrowdsale { - - constructor ( - uint256 rate, - address wallet, - IERC20 token, - address tokenWallet - ) - public - Crowdsale(rate, wallet, token) - AllowanceCrowdsale(tokenWallet) - { - } - + constructor (uint256 rate, address wallet, IERC20 token, address tokenWallet) + public + Crowdsale(rate, wallet, token) + AllowanceCrowdsale(tokenWallet) + {} } diff --git a/contracts/mocks/ArraysImpl.sol b/contracts/mocks/ArraysImpl.sol index 8a2b9ec51..77c7a517b 100644 --- a/contracts/mocks/ArraysImpl.sol +++ b/contracts/mocks/ArraysImpl.sol @@ -3,16 +3,15 @@ pragma solidity ^0.4.24; import "../utils/Arrays.sol"; contract ArraysImpl { + using Arrays for uint256[]; - using Arrays for uint256[]; + uint256[] private array; - uint256[] private array; + constructor (uint256[] _array) public { + array = _array; + } - constructor(uint256[] _array) public { - array = _array; - } - - function findUpperBound(uint256 _element) external view returns (uint256) { - return array.findUpperBound(_element); - } + function findUpperBound(uint256 _element) external view returns (uint256) { + return array.findUpperBound(_element); + } } diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index 176033b7f..4b8cd5560 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -4,17 +4,9 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/CappedCrowdsale.sol"; contract CappedCrowdsaleImpl is CappedCrowdsale { - - constructor ( - uint256 rate, - address wallet, - IERC20 token, - uint256 cap - ) - public - Crowdsale(rate, wallet, token) - CappedCrowdsale(cap) - { - } - + constructor (uint256 rate, address wallet, IERC20 token, uint256 cap) + public + Crowdsale(rate, wallet, token) + CappedCrowdsale(cap) + {} } diff --git a/contracts/mocks/CapperRoleMock.sol b/contracts/mocks/CapperRoleMock.sol index 118058f39..eb3b92b62 100644 --- a/contracts/mocks/CapperRoleMock.sol +++ b/contracts/mocks/CapperRoleMock.sol @@ -3,15 +3,15 @@ pragma solidity ^0.4.24; import "../access/roles/CapperRole.sol"; contract CapperRoleMock is CapperRole { - function removeCapper(address account) public { - _removeCapper(account); - } + function removeCapper(address account) public { + _removeCapper(account); + } - function onlyCapperMock() public view onlyCapper { - } + function onlyCapperMock() public view onlyCapper { + } - // Causes a compilation error if super._removeCapper is not internal - function _removeCapper(address account) internal { - super._removeCapper(account); - } + // Causes a compilation error if super._removeCapper is not internal + function _removeCapper(address account) internal { + super._removeCapper(account); + } } diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 3e30c21a2..2f1faf804 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -4,13 +4,13 @@ import "../payment/escrow/ConditionalEscrow.sol"; // mock class using ConditionalEscrow contract ConditionalEscrowMock is ConditionalEscrow { - mapping(address => bool) private _allowed; + mapping(address => bool) private _allowed; - function setAllowed(address payee, bool allowed) public { - _allowed[payee] = allowed; - } + function setAllowed(address payee, bool allowed) public { + _allowed[payee] = allowed; + } - function withdrawalAllowed(address payee) public view returns (bool) { - return _allowed[payee]; - } + function withdrawalAllowed(address payee) public view returns (bool) { + return _allowed[payee]; + } } diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol index 3c958ba97..15ff1361e 100644 --- a/contracts/mocks/CounterImpl.sol +++ b/contracts/mocks/CounterImpl.sol @@ -3,18 +3,15 @@ pragma solidity ^0.4.24; import "../drafts/Counter.sol"; contract CounterImpl { - using Counter for Counter.Counter; + using Counter for Counter.Counter; - uint256 public theId; + uint256 public theId; - // use whatever key you want to track your counters - mapping(string => Counter.Counter) private _counters; + // use whatever key you want to track your counters + mapping(string => Counter.Counter) private _counters; - function doThing(string key) - public - returns (uint256) - { - theId = _counters[key].next(); - return theId; - } + function doThing(string key) public returns (uint256) { + theId = _counters[key].next(); + return theId; + } } diff --git a/contracts/mocks/CrowdsaleMock.sol b/contracts/mocks/CrowdsaleMock.sol index 834105e6a..0555b1abc 100644 --- a/contracts/mocks/CrowdsaleMock.sol +++ b/contracts/mocks/CrowdsaleMock.sol @@ -3,7 +3,5 @@ pragma solidity ^0.4.24; import "../crowdsale/Crowdsale.sol"; contract CrowdsaleMock is Crowdsale { - constructor(uint256 rate, address wallet, IERC20 token) public - Crowdsale(rate, wallet, token) { - } + constructor (uint256 rate, address wallet, IERC20 token) public Crowdsale(rate, wallet, token) {} } diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index eea706326..fbc526c45 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -4,12 +4,5 @@ import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; contract ERC20DetailedMock is ERC20, ERC20Detailed { - constructor( - string name, - string symbol, - uint8 decimals - ) - ERC20Detailed(name, symbol, decimals) - public - {} + constructor (string name, string symbol, uint8 decimals) ERC20Detailed(name, symbol, decimals) public {} } diff --git a/contracts/mocks/ECDSAMock.sol b/contracts/mocks/ECDSAMock.sol index 9f489069f..862ad9b35 100644 --- a/contracts/mocks/ECDSAMock.sol +++ b/contracts/mocks/ECDSAMock.sol @@ -3,21 +3,13 @@ pragma solidity ^0.4.24; import "../cryptography/ECDSA.sol"; contract ECDSAMock { - using ECDSA for bytes32; + using ECDSA for bytes32; - function recover(bytes32 hash, bytes signature) - public - pure - returns (address) - { - return hash.recover(signature); - } + function recover(bytes32 hash, bytes signature) public pure returns (address) { + return hash.recover(signature); + } - function toEthSignedMessageHash(bytes32 hash) - public - pure - returns (bytes32) - { - return hash.toEthSignedMessageHash(); - } + function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) { + return hash.toEthSignedMessageHash(); + } } diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index e41901a32..0ed65df24 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -11,56 +11,45 @@ import "../../introspection/IERC165.sol"; * solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it */ contract SupportsInterfaceWithLookupMock is IERC165 { + bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; + /** + * 0x01ffc9a7 === + * bytes4(keccak256('supportsInterface(bytes4)')) + */ - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ + /** + * @dev a mapping of interface id to whether or not it's supported + */ + mapping(bytes4 => bool) private _supportedInterfaces; - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; + /** + * @dev A contract implementing SupportsInterfaceWithLookup + * implement ERC165 itself + */ + constructor () public { + _registerInterface(InterfaceId_ERC165); + } - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() - public - { - _registerInterface(InterfaceId_ERC165); - } + /** + * @dev implement supportsInterface(bytes4) using a lookup table + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool) { + return _supportedInterfaces[interfaceId]; + } - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) - external - view - returns (bool) - { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) - internal - { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } + /** + * @dev private method for registering an interface + */ + function _registerInterface(bytes4 interfaceId) internal { + require(interfaceId != 0xffffffff); + _supportedInterfaces[interfaceId] = true; + } } contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock { - constructor (bytes4[] interfaceIds) - public - { - for (uint256 i = 0; i < interfaceIds.length; i++) { - _registerInterface(interfaceIds[i]); + constructor (bytes4[] interfaceIds) public { + for (uint256 i = 0; i < interfaceIds.length; i++) { + _registerInterface(interfaceIds[i]); + } } - } } diff --git a/contracts/mocks/ERC165/ERC165NotSupported.sol b/contracts/mocks/ERC165/ERC165NotSupported.sol index 156ef8e8b..c1a39db19 100644 --- a/contracts/mocks/ERC165/ERC165NotSupported.sol +++ b/contracts/mocks/ERC165/ERC165NotSupported.sol @@ -1,5 +1,3 @@ pragma solidity ^0.4.24; -contract ERC165NotSupported { - -} +contract ERC165NotSupported {} diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index 559cea0d7..b85397b44 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -3,29 +3,17 @@ pragma solidity ^0.4.24; import "../introspection/ERC165Checker.sol"; contract ERC165CheckerMock { - using ERC165Checker for address; + using ERC165Checker for address; - function supportsERC165(address account) - public - view - returns (bool) - { - return account._supportsERC165(); - } + function supportsERC165(address account) public view returns (bool) { + return account._supportsERC165(); + } - function supportsInterface(address account, bytes4 interfaceId) - public - view - returns (bool) - { - return account._supportsInterface(interfaceId); - } + function supportsInterface(address account, bytes4 interfaceId) public view returns (bool) { + return account._supportsInterface(interfaceId); + } - function supportsAllInterfaces(address account, bytes4[] interfaceIds) - public - view - returns (bool) - { - return account._supportsAllInterfaces(interfaceIds); - } + function supportsAllInterfaces(address account, bytes4[] interfaceIds) public view returns (bool) { + return account._supportsAllInterfaces(interfaceIds); + } } diff --git a/contracts/mocks/ERC165Mock.sol b/contracts/mocks/ERC165Mock.sol index c42ba62f2..ad48a9de3 100644 --- a/contracts/mocks/ERC165Mock.sol +++ b/contracts/mocks/ERC165Mock.sol @@ -3,9 +3,7 @@ pragma solidity ^0.4.24; import "../introspection/ERC165.sol"; contract ERC165Mock is ERC165 { - function registerInterface(bytes4 interfaceId) - public - { - _registerInterface(interfaceId); - } + function registerInterface(bytes4 interfaceId) public { + _registerInterface(interfaceId); + } } diff --git a/contracts/mocks/ERC20BurnableMock.sol b/contracts/mocks/ERC20BurnableMock.sol index 2c8b3b54a..7456f9642 100644 --- a/contracts/mocks/ERC20BurnableMock.sol +++ b/contracts/mocks/ERC20BurnableMock.sol @@ -3,9 +3,7 @@ pragma solidity ^0.4.24; import "../token/ERC20/ERC20Burnable.sol"; contract ERC20BurnableMock is ERC20Burnable { - - constructor(address initialAccount, uint256 initialBalance) public { - _mint(initialAccount, initialBalance); - } - + constructor (address initialAccount, uint256 initialBalance) public { + _mint(initialAccount, initialBalance); + } } diff --git a/contracts/mocks/ERC20Mock.sol b/contracts/mocks/ERC20Mock.sol index ab0877653..3742f808d 100644 --- a/contracts/mocks/ERC20Mock.sol +++ b/contracts/mocks/ERC20Mock.sol @@ -4,21 +4,19 @@ import "../token/ERC20/ERC20.sol"; // mock class using ERC20 contract ERC20Mock is ERC20 { + constructor (address initialAccount, uint256 initialBalance) public { + _mint(initialAccount, initialBalance); + } - constructor(address initialAccount, uint256 initialBalance) public { - _mint(initialAccount, initialBalance); - } + function mint(address account, uint256 amount) public { + _mint(account, amount); + } - function mint(address account, uint256 amount) public { - _mint(account, amount); - } - - function burn(address account, uint256 amount) public { - _burn(account, amount); - } - - function burnFrom(address account, uint256 amount) public { - _burnFrom(account, amount); - } + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + function burnFrom(address account, uint256 amount) public { + _burnFrom(account, amount); + } } diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index c6c0fd5ed..59a8a0952 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -5,9 +5,7 @@ import "./PauserRoleMock.sol"; // mock class using ERC20Pausable contract ERC20PausableMock is ERC20Pausable, PauserRoleMock { - - constructor(address initialAccount, uint initialBalance) public { - _mint(initialAccount, initialBalance); - } - + constructor (address initialAccount, uint initialBalance) public { + _mint(initialAccount, initialBalance); + } } diff --git a/contracts/mocks/ERC20WithMetadataMock.sol b/contracts/mocks/ERC20WithMetadataMock.sol index ec2d122a1..6eb4b9306 100644 --- a/contracts/mocks/ERC20WithMetadataMock.sol +++ b/contracts/mocks/ERC20WithMetadataMock.sol @@ -4,8 +4,5 @@ import "../token/ERC20/ERC20.sol"; import "../drafts/ERC1046/TokenMetadata.sol"; contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { - constructor(string tokenURI) public - ERC20WithMetadata(tokenURI) - { - } + constructor (string tokenURI) public ERC20WithMetadata(tokenURI) {} } diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index 2d85e7372..5199ef417 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -10,23 +10,18 @@ import "../token/ERC721/ERC721Burnable.sol"; * This mock just provides a public mint and burn functions for testing purposes, * and a public setter for metadata URI */ -contract ERC721FullMock - is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { +contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { + constructor (string name, string symbol) public ERC721Mintable() ERC721Full(name, symbol) {} - constructor(string name, string symbol) public - ERC721Mintable() - ERC721Full(name, symbol) - {} + function exists(uint256 tokenId) public view returns (bool) { + return _exists(tokenId); + } - function exists(uint256 tokenId) public view returns (bool) { - return _exists(tokenId); - } + function setTokenURI(uint256 tokenId, string uri) public { + _setTokenURI(tokenId, uri); + } - function setTokenURI(uint256 tokenId, string uri) public { - _setTokenURI(tokenId, uri); - } - - function removeTokenFrom(address from, uint256 tokenId) public { - _removeTokenFrom(from, tokenId); - } + function removeTokenFrom(address from, uint256 tokenId) public { + _removeTokenFrom(from, tokenId); + } } diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index 51d3ff4f6..6e5aae6f5 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -8,13 +8,6 @@ import "../token/ERC721/ERC721Burnable.sol"; /** * @title ERC721MintableBurnableImpl */ -contract ERC721MintableBurnableImpl - is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { - - constructor() - ERC721Mintable() - ERC721Full("Test", "TEST") - public - { - } +contract ERC721MintableBurnableImpl is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { + constructor () ERC721Mintable() ERC721Full("Test", "TEST") public {} } diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index 514d3bdbe..98bfe99bc 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -7,11 +7,11 @@ import "../token/ERC721/ERC721.sol"; * This mock just provides a public mint and burn functions for testing purposes */ contract ERC721Mock is ERC721 { - function mint(address to, uint256 tokenId) public { - _mint(to, tokenId); - } + function mint(address to, uint256 tokenId) public { + _mint(to, tokenId); + } - function burn(uint256 tokenId) public { - _burn(ownerOf(tokenId), tokenId); - } + function burn(uint256 tokenId) public { + _burn(ownerOf(tokenId), tokenId); + } } diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index 9751d04cb..4470ea726 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -8,15 +8,15 @@ import "./PauserRoleMock.sol"; * This mock just provides a public mint, burn and exists functions for testing purposes */ contract ERC721PausableMock is ERC721Pausable, PauserRoleMock { - function mint(address to, uint256 tokenId) public { - super._mint(to, tokenId); - } + function mint(address to, uint256 tokenId) public { + super._mint(to, tokenId); + } - function burn(uint256 tokenId) public { - super._burn(ownerOf(tokenId), tokenId); - } + function burn(uint256 tokenId) public { + super._burn(ownerOf(tokenId), tokenId); + } - function exists(uint256 tokenId) public view returns (bool) { - return super._exists(tokenId); - } + function exists(uint256 tokenId) public view returns (bool) { + return super._exists(tokenId); + } } diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 57fb04e3a..7e469b271 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -3,39 +3,19 @@ pragma solidity ^0.4.24; import "../token/ERC721/IERC721Receiver.sol"; contract ERC721ReceiverMock is IERC721Receiver { - bytes4 private _retval; - bool private _reverts; + bytes4 private _retval; + bool private _reverts; - event Received( - address operator, - address from, - uint256 tokenId, - bytes data, - uint256 gas - ); + event Received(address operator, address from, uint256 tokenId, bytes data, uint256 gas); - constructor(bytes4 retval, bool reverts) public { - _retval = retval; - _reverts = reverts; - } + constructor (bytes4 retval, bool reverts) public { + _retval = retval; + _reverts = reverts; + } - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes data - ) - public - returns(bytes4) - { - require(!_reverts); - emit Received( - operator, - from, - tokenId, - data, - gasleft() // msg.gas was deprecated in solidityv0.4.21 - ); - return _retval; - } + function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public returns (bytes4) { + require(!_reverts); + emit Received(operator, from, tokenId, data, gasleft()); + return _retval; + } } diff --git a/contracts/mocks/EventEmitter.sol b/contracts/mocks/EventEmitter.sol index 71582d9f5..257b23651 100644 --- a/contracts/mocks/EventEmitter.sol +++ b/contracts/mocks/EventEmitter.sol @@ -1,62 +1,54 @@ pragma solidity ^0.4.24; contract EventEmitter { - event Argumentless(); - event ShortUint(uint8 value); - event ShortInt(int8 value); - event LongUint(uint256 value); - event LongInt(int256 value); - event Address(address value); - event Boolean(bool value); - event String(string value); - event LongUintBooleanString( - uint256 uintValue, - bool booleanValue, - string stringValue - ); + event Argumentless(); + event ShortUint(uint8 value); + event ShortInt(int8 value); + event LongUint(uint256 value); + event LongInt(int256 value); + event Address(address value); + event Boolean(bool value); + event String(string value); + event LongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue); - function emitArgumentless() public { - emit Argumentless(); - } + function emitArgumentless() public { + emit Argumentless(); + } - function emitShortUint(uint8 value) public { - emit ShortUint(value); - } + function emitShortUint(uint8 value) public { + emit ShortUint(value); + } - function emitShortInt(int8 value) public { - emit ShortInt(value); - } + function emitShortInt(int8 value) public { + emit ShortInt(value); + } - function emitLongUint(uint256 value) public { - emit LongUint(value); - } + function emitLongUint(uint256 value) public { + emit LongUint(value); + } - function emitLongInt(int256 value) public { - emit LongInt(value); - } + function emitLongInt(int256 value) public { + emit LongInt(value); + } - function emitAddress(address value) public { - emit Address(value); - } + function emitAddress(address value) public { + emit Address(value); + } - function emitBoolean(bool value) public { - emit Boolean(value); - } + function emitBoolean(bool value) public { + emit Boolean(value); + } - function emitString(string value) public { - emit String(value); - } + function emitString(string value) public { + emit String(value); + } - function emitLongUintBooleanString( - uint256 uintValue, - bool booleanValue, - string stringValue) - public { - emit LongUintBooleanString(uintValue, booleanValue, stringValue); - } + function emitLongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue) public { + emit LongUintBooleanString(uintValue, booleanValue, stringValue); + } - function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public { - emit LongUint(uintValue); - emit Boolean(boolValue); - } + function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public { + emit LongUint(uintValue); + emit Boolean(boolValue); + } } diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 084780b1d..0dee94ff1 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -5,17 +5,9 @@ import "../crowdsale/distribution/FinalizableCrowdsale.sol"; contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { - constructor ( - uint256 openingTime, - uint256 closingTime, - uint256 rate, - address wallet, - IERC20 token - ) - public - Crowdsale(rate, wallet, token) - TimedCrowdsale(openingTime, closingTime) - { - } - + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + public + Crowdsale(rate, wallet, token) + TimedCrowdsale(openingTime, closingTime) + {} } diff --git a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol index 6f1f2e2a0..3f5d30b21 100644 --- a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol +++ b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol @@ -4,20 +4,17 @@ import "../crowdsale/price/IncreasingPriceCrowdsale.sol"; import "../math/SafeMath.sol"; contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale { - - constructor ( - uint256 openingTime, - uint256 closingTime, - address wallet, - IERC20 token, - uint256 initialRate, - uint256 finalRate - ) - public - Crowdsale(initialRate, wallet, token) - TimedCrowdsale(openingTime, closingTime) - IncreasingPriceCrowdsale(initialRate, finalRate) - { - } - + constructor ( + uint256 openingTime, + uint256 closingTime, + address wallet, + IERC20 token, + uint256 initialRate, + uint256 finalRate + ) + public + Crowdsale(initialRate, wallet, token) + TimedCrowdsale(openingTime, closingTime) + IncreasingPriceCrowdsale(initialRate, finalRate) + {} } diff --git a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol index 1bcb95301..296dbc26f 100644 --- a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol +++ b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol @@ -4,16 +4,7 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol"; import "./CapperRoleMock.sol"; -contract IndividuallyCappedCrowdsaleImpl - is IndividuallyCappedCrowdsale, CapperRoleMock { - - constructor( - uint256 rate, - address wallet, - IERC20 token - ) - public - Crowdsale(rate, wallet, token) - { - } +contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock { + constructor (uint256 rate, address wallet, IERC20 token) public Crowdsale(rate, wallet, token) + {} } diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index 72f7fc204..c6d1f107a 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -3,15 +3,15 @@ pragma solidity ^0.4.24; import "../math/Math.sol"; contract MathMock { - function max(uint256 a, uint256 b) public pure returns (uint256) { - return Math.max(a, b); - } + function max(uint256 a, uint256 b) public pure returns (uint256) { + return Math.max(a, b); + } - function min(uint256 a, uint256 b) public pure returns (uint256) { - return Math.min(a, b); - } + function min(uint256 a, uint256 b) public pure returns (uint256) { + return Math.min(a, b); + } - function average(uint256 a, uint256 b) public pure returns (uint256) { - return Math.average(a, b); - } + function average(uint256 a, uint256 b) public pure returns (uint256) { + return Math.average(a, b); + } } diff --git a/contracts/mocks/MerkleProofWrapper.sol b/contracts/mocks/MerkleProofWrapper.sol index b359dc790..02a1d8cc6 100644 --- a/contracts/mocks/MerkleProofWrapper.sol +++ b/contracts/mocks/MerkleProofWrapper.sol @@ -3,16 +3,7 @@ pragma solidity ^0.4.24; import { MerkleProof } from "../cryptography/MerkleProof.sol"; contract MerkleProofWrapper { - - function verify( - bytes32[] proof, - bytes32 root, - bytes32 leaf - ) - public - pure - returns (bool) - { - return MerkleProof.verify(proof, root, leaf); - } + function verify(bytes32[] proof, bytes32 root, bytes32 leaf) public pure returns (bool) { + return MerkleProof.verify(proof, root, leaf); + } } diff --git a/contracts/mocks/MintedCrowdsaleImpl.sol b/contracts/mocks/MintedCrowdsaleImpl.sol index 518371b75..48d6c167d 100644 --- a/contracts/mocks/MintedCrowdsaleImpl.sol +++ b/contracts/mocks/MintedCrowdsaleImpl.sol @@ -4,15 +4,5 @@ import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; contract MintedCrowdsaleImpl is MintedCrowdsale { - - constructor ( - uint256 rate, - address wallet, - ERC20Mintable token - ) - public - Crowdsale(rate, wallet, token) - { - } - + constructor (uint256 rate, address wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) {} } diff --git a/contracts/mocks/MinterRoleMock.sol b/contracts/mocks/MinterRoleMock.sol index 45e5a4195..0755c1221 100644 --- a/contracts/mocks/MinterRoleMock.sol +++ b/contracts/mocks/MinterRoleMock.sol @@ -3,15 +3,15 @@ pragma solidity ^0.4.24; import "../access/roles/MinterRole.sol"; contract MinterRoleMock is MinterRole { - function removeMinter(address account) public { - _removeMinter(account); - } + function removeMinter(address account) public { + _removeMinter(account); + } - function onlyMinterMock() public view onlyMinter { - } + function onlyMinterMock() public view onlyMinter { + } - // Causes a compilation error if super._removeMinter is not internal - function _removeMinter(address account) internal { - super._removeMinter(account); - } + // Causes a compilation error if super._removeMinter is not internal + function _removeMinter(address account) internal { + super._removeMinter(account); + } } diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol index e16a89012..6a1bf1e2c 100644 --- a/contracts/mocks/OwnableMock.sol +++ b/contracts/mocks/OwnableMock.sol @@ -2,5 +2,4 @@ pragma solidity ^0.4.24; import "../ownership/Ownable.sol"; -contract OwnableMock is Ownable { -} +contract OwnableMock is Ownable {} diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index 72ec843ed..c2dcda1c5 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -5,20 +5,19 @@ import "./PauserRoleMock.sol"; // mock class using Pausable contract PausableMock is Pausable, PauserRoleMock { - bool public drasticMeasureTaken; - uint256 public count; + bool public drasticMeasureTaken; + uint256 public count; - constructor() public { - drasticMeasureTaken = false; - count = 0; - } + constructor () public { + drasticMeasureTaken = false; + count = 0; + } - function normalProcess() external whenNotPaused { - count++; - } - - function drasticMeasure() external whenPaused { - drasticMeasureTaken = true; - } + function normalProcess() external whenNotPaused { + count++; + } + function drasticMeasure() external whenPaused { + drasticMeasureTaken = true; + } } diff --git a/contracts/mocks/PauserRoleMock.sol b/contracts/mocks/PauserRoleMock.sol index 267101e4a..22f03f5b0 100644 --- a/contracts/mocks/PauserRoleMock.sol +++ b/contracts/mocks/PauserRoleMock.sol @@ -3,15 +3,15 @@ pragma solidity ^0.4.24; import "../access/roles/PauserRole.sol"; contract PauserRoleMock is PauserRole { - function removePauser(address account) public { - _removePauser(account); - } + function removePauser(address account) public { + _removePauser(account); + } - function onlyPauserMock() public view onlyPauser { - } + function onlyPauserMock() public view onlyPauser { + } - // Causes a compilation error if super._removePauser is not internal - function _removePauser(address account) internal { - super._removePauser(account); - } + // Causes a compilation error if super._removePauser is not internal + function _removePauser(address account) internal { + super._removePauser(account); + } } diff --git a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol index 98d056c66..df71456c7 100644 --- a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol @@ -4,18 +4,9 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/PostDeliveryCrowdsale.sol"; contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale { - - constructor ( - uint256 openingTime, - uint256 closingTime, - uint256 rate, - address wallet, - IERC20 token - ) - public - TimedCrowdsale(openingTime, closingTime) - Crowdsale(rate, wallet, token) - { - } - + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + public + TimedCrowdsale(openingTime, closingTime) + Crowdsale(rate, wallet, token) + {} } diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index 63076c904..d35e97e02 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -4,12 +4,10 @@ import "../payment/PullPayment.sol"; // mock class using PullPayment contract PullPaymentMock is PullPayment { + constructor () public payable { } - constructor() public payable { } - - // test helper function to call asyncTransfer - function callTransfer(address dest, uint256 amount) public { - _asyncTransfer(dest, amount); - } - + // test helper function to call asyncTransfer + function callTransfer(address dest, uint256 amount) public { + _asyncTransfer(dest, amount); + } } diff --git a/contracts/mocks/ReentrancyAttack.sol b/contracts/mocks/ReentrancyAttack.sol index 96231de27..c18a1020b 100644 --- a/contracts/mocks/ReentrancyAttack.sol +++ b/contracts/mocks/ReentrancyAttack.sol @@ -2,9 +2,9 @@ pragma solidity ^0.4.24; contract ReentrancyAttack { - function callSender(bytes4 data) public { - // solium-disable-next-line security/no-low-level-calls - require(msg.sender.call(abi.encodeWithSelector(data))); - } + function callSender(bytes4 data) public { + // solium-disable-next-line security/no-low-level-calls + require(msg.sender.call(abi.encodeWithSelector(data))); + } } diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index 474ecd433..5aac7603c 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -4,41 +4,39 @@ import "../utils/ReentrancyGuard.sol"; import "./ReentrancyAttack.sol"; contract ReentrancyMock is ReentrancyGuard { + uint256 public counter; - uint256 public counter; - - constructor() public { - counter = 0; - } - - function callback() external nonReentrant { - count(); - } - - function countLocalRecursive(uint256 n) public nonReentrant { - if (n > 0) { - count(); - countLocalRecursive(n - 1); + constructor () public { + counter = 0; } - } - function countThisRecursive(uint256 n) public nonReentrant { - if (n > 0) { - count(); - // solium-disable-next-line security/no-low-level-calls - bool result = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); - require(result == true); + function callback() external nonReentrant { + count(); } - } - function countAndCall(ReentrancyAttack attacker) public nonReentrant { - count(); - bytes4 func = bytes4(keccak256("callback()")); - attacker.callSender(func); - } + function countLocalRecursive(uint256 n) public nonReentrant { + if (n > 0) { + count(); + countLocalRecursive(n - 1); + } + } - function count() private { - counter += 1; - } + function countThisRecursive(uint256 n) public nonReentrant { + if (n > 0) { + count(); + // solium-disable-next-line security/no-low-level-calls + bool result = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); + require(result == true); + } + } + function countAndCall(ReentrancyAttack attacker) public nonReentrant { + count(); + bytes4 func = bytes4(keccak256("callback()")); + attacker.callSender(func); + } + + function count() private { + counter += 1; + } } diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index a14dfbcb3..6759d9aff 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -4,20 +4,17 @@ import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; contract RefundableCrowdsaleImpl is RefundableCrowdsale { - - constructor ( - uint256 openingTime, - uint256 closingTime, - uint256 rate, - address wallet, - ERC20Mintable token, - uint256 goal - ) - public - Crowdsale(rate, wallet, token) - TimedCrowdsale(openingTime, closingTime) - RefundableCrowdsale(goal) - { - } - + constructor ( + uint256 openingTime, + uint256 closingTime, + uint256 rate, + address wallet, + ERC20Mintable token, + uint256 goal + ) + public + Crowdsale(rate, wallet, token) + TimedCrowdsale(openingTime, closingTime) + RefundableCrowdsale(goal) + {} } diff --git a/contracts/mocks/RolesMock.sol b/contracts/mocks/RolesMock.sol index bfcee20ee..db71ca536 100644 --- a/contracts/mocks/RolesMock.sol +++ b/contracts/mocks/RolesMock.sol @@ -3,19 +3,19 @@ pragma solidity ^0.4.24; import "../access/Roles.sol"; contract RolesMock { - using Roles for Roles.Role; + using Roles for Roles.Role; - Roles.Role private dummyRole; + Roles.Role private dummyRole; - function add(address account) public { - dummyRole.add(account); - } + function add(address account) public { + dummyRole.add(account); + } - function remove(address account) public { - dummyRole.remove(account); - } + function remove(address account) public { + dummyRole.remove(account); + } - function has(address account) public view returns (bool) { - return dummyRole.has(account); - } + function has(address account) public view returns (bool) { + return dummyRole.has(account); + } } diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 7e639f86f..9c0af1312 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -4,109 +4,109 @@ import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; contract ERC20FailingMock { - uint256 private _allowance; + uint256 private _allowance; - function transfer(address, uint256) public returns (bool) { - return false; - } + function transfer(address, uint256) public returns (bool) { + return false; + } - function transferFrom(address, address, uint256) public returns (bool) { - return false; - } + function transferFrom(address, address, uint256) public returns (bool) { + return false; + } - function approve(address, uint256) public returns (bool) { - return false; - } + function approve(address, uint256) public returns (bool) { + return false; + } - function allowance(address, address) public view returns (uint256) { - return 0; - } + function allowance(address, address) public view returns (uint256) { + return 0; + } } contract ERC20SucceedingMock { - uint256 private _allowance; + uint256 private _allowance; - function transfer(address, uint256) public returns (bool) { - return true; - } + function transfer(address, uint256) public returns (bool) { + return true; + } - function transferFrom(address, address, uint256) public returns (bool) { - return true; - } + function transferFrom(address, address, uint256) public returns (bool) { + return true; + } - function approve(address, uint256) public returns (bool) { - return true; - } + function approve(address, uint256) public returns (bool) { + return true; + } - function setAllowance(uint256 allowance_) public { - _allowance = allowance_; - } + function setAllowance(uint256 allowance_) public { + _allowance = allowance_; + } - function allowance(address, address) public view returns (uint256) { - return _allowance; - } + function allowance(address, address) public view returns (uint256) { + return _allowance; + } } contract SafeERC20Helper { - using SafeERC20 for IERC20; + using SafeERC20 for IERC20; - IERC20 private _failing; - IERC20 private _succeeding; + IERC20 private _failing; + IERC20 private _succeeding; - constructor() public { - _failing = IERC20(new ERC20FailingMock()); - _succeeding = IERC20(new ERC20SucceedingMock()); - } + constructor () public { + _failing = IERC20(new ERC20FailingMock()); + _succeeding = IERC20(new ERC20SucceedingMock()); + } - // Using _failing + // Using _failing - function doFailingTransfer() public { - _failing.safeTransfer(address(0), 0); - } + function doFailingTransfer() public { + _failing.safeTransfer(address(0), 0); + } - function doFailingTransferFrom() public { - _failing.safeTransferFrom(address(0), address(0), 0); - } + function doFailingTransferFrom() public { + _failing.safeTransferFrom(address(0), address(0), 0); + } - function doFailingApprove() public { - _failing.safeApprove(address(0), 0); - } + function doFailingApprove() public { + _failing.safeApprove(address(0), 0); + } - function doFailingIncreaseAllowance() public { - _failing.safeIncreaseAllowance(address(0), 0); - } + function doFailingIncreaseAllowance() public { + _failing.safeIncreaseAllowance(address(0), 0); + } - function doFailingDecreaseAllowance() public { - _failing.safeDecreaseAllowance(address(0), 0); - } + function doFailingDecreaseAllowance() public { + _failing.safeDecreaseAllowance(address(0), 0); + } - // Using _succeeding + // Using _succeeding - function doSucceedingTransfer() public { - _succeeding.safeTransfer(address(0), 0); - } + function doSucceedingTransfer() public { + _succeeding.safeTransfer(address(0), 0); + } - function doSucceedingTransferFrom() public { - _succeeding.safeTransferFrom(address(0), address(0), 0); - } + function doSucceedingTransferFrom() public { + _succeeding.safeTransferFrom(address(0), address(0), 0); + } - function doSucceedingApprove(uint256 amount) public { - _succeeding.safeApprove(address(0), amount); - } + function doSucceedingApprove(uint256 amount) public { + _succeeding.safeApprove(address(0), amount); + } - function doSucceedingIncreaseAllowance(uint256 amount) public { - _succeeding.safeIncreaseAllowance(address(0), amount); - } + function doSucceedingIncreaseAllowance(uint256 amount) public { + _succeeding.safeIncreaseAllowance(address(0), amount); + } - function doSucceedingDecreaseAllowance(uint256 amount) public { - _succeeding.safeDecreaseAllowance(address(0), amount); - } + function doSucceedingDecreaseAllowance(uint256 amount) public { + _succeeding.safeDecreaseAllowance(address(0), amount); + } - function setAllowance(uint256 allowance_) public { - ERC20SucceedingMock(_succeeding).setAllowance(allowance_); - } + function setAllowance(uint256 allowance_) public { + ERC20SucceedingMock(_succeeding).setAllowance(allowance_); + } - function allowance() public view returns (uint256) { - return _succeeding.allowance(address(0), address(0)); - } + function allowance() public view returns (uint256) { + return _succeeding.allowance(address(0), address(0)); + } } diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index 7ddf17e9f..69ed0c38c 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -3,24 +3,23 @@ pragma solidity ^0.4.24; import "../math/SafeMath.sol"; contract SafeMathMock { + function mul(uint256 a, uint256 b) public pure returns (uint256) { + return SafeMath.mul(a, b); + } - function mul(uint256 a, uint256 b) public pure returns (uint256) { - return SafeMath.mul(a, b); - } + function div(uint256 a, uint256 b) public pure returns (uint256) { + return SafeMath.div(a, b); + } - function div(uint256 a, uint256 b) public pure returns (uint256) { - return SafeMath.div(a, b); - } + function sub(uint256 a, uint256 b) public pure returns (uint256) { + return SafeMath.sub(a, b); + } - function sub(uint256 a, uint256 b) public pure returns (uint256) { - return SafeMath.sub(a, b); - } + function add(uint256 a, uint256 b) public pure returns (uint256) { + return SafeMath.add(a, b); + } - function add(uint256 a, uint256 b) public pure returns (uint256) { - return SafeMath.add(a, b); - } - - function mod(uint256 a, uint256 b) public pure returns (uint256) { - return SafeMath.mod(a, b); - } + function mod(uint256 a, uint256 b) public pure returns (uint256) { + return SafeMath.mod(a, b); + } } diff --git a/contracts/mocks/SecondaryMock.sol b/contracts/mocks/SecondaryMock.sol index 268c12516..faf88f4e3 100644 --- a/contracts/mocks/SecondaryMock.sol +++ b/contracts/mocks/SecondaryMock.sol @@ -3,6 +3,5 @@ pragma solidity ^0.4.24; import "../ownership/Secondary.sol"; contract SecondaryMock is Secondary { - function onlyPrimaryMock() public view onlyPrimary { - } + function onlyPrimaryMock() public view onlyPrimary {} } diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index 85076eae6..21572102a 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -4,70 +4,25 @@ import "../drafts/SignatureBouncer.sol"; import "./SignerRoleMock.sol"; contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { - function checkValidSignature(address account, bytes signature) - public - view - returns (bool) - { - return _isValidSignature(account, signature); - } + function checkValidSignature(address account, bytes signature) public view returns (bool) { + return _isValidSignature(account, signature); + } - function onlyWithValidSignature(bytes signature) - public - onlyValidSignature(signature) - view - { + function onlyWithValidSignature(bytes signature) public onlyValidSignature(signature) view {} - } + function checkValidSignatureAndMethod(address account, bytes signature) public view returns (bool) { + return _isValidSignatureAndMethod(account, signature); + } - function checkValidSignatureAndMethod(address account, bytes signature) - public - view - returns (bool) - { - return _isValidSignatureAndMethod(account, signature); - } + function onlyWithValidSignatureAndMethod(bytes signature) public onlyValidSignatureAndMethod(signature) view {} - function onlyWithValidSignatureAndMethod(bytes signature) - public - onlyValidSignatureAndMethod(signature) - view - { + function checkValidSignatureAndData(address account, bytes, uint, bytes signature) public view returns (bool) { + return _isValidSignatureAndData(account, signature); + } - } + function onlyWithValidSignatureAndData(uint, bytes signature) public onlyValidSignatureAndData(signature) view {} - function checkValidSignatureAndData( - address account, - bytes, - uint, - bytes signature - ) - public - view - returns (bool) - { - return _isValidSignatureAndData(account, signature); - } + function theWrongMethod(bytes) public pure {} - function onlyWithValidSignatureAndData(uint, bytes signature) - public - onlyValidSignatureAndData(signature) - view - { - - } - - function theWrongMethod(bytes) - public - pure - { - - } - - function tooShortMsgData() - public - onlyValidSignatureAndData("") - view - { - } + function tooShortMsgData() public onlyValidSignatureAndData("") view {} } diff --git a/contracts/mocks/SignerRoleMock.sol b/contracts/mocks/SignerRoleMock.sol index faf92db68..7eb3c3475 100644 --- a/contracts/mocks/SignerRoleMock.sol +++ b/contracts/mocks/SignerRoleMock.sol @@ -3,15 +3,15 @@ pragma solidity ^0.4.24; import "../access/roles/SignerRole.sol"; contract SignerRoleMock is SignerRole { - function removeSigner(address account) public { - _removeSigner(account); - } + function removeSigner(address account) public { + _removeSigner(account); + } - function onlySignerMock() public view onlySigner { - } + function onlySignerMock() public view onlySigner { + } - // Causes a compilation error if super._removeSigner is not internal - function _removeSigner(address account) internal { - super._removeSigner(account); - } + // Causes a compilation error if super._removeSigner is not internal + function _removeSigner(address account) internal { + super._removeSigner(account); + } } diff --git a/contracts/mocks/TimedCrowdsaleImpl.sol b/contracts/mocks/TimedCrowdsaleImpl.sol index f16e5eb2a..b826c31e5 100644 --- a/contracts/mocks/TimedCrowdsaleImpl.sol +++ b/contracts/mocks/TimedCrowdsaleImpl.sol @@ -4,18 +4,9 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/TimedCrowdsale.sol"; contract TimedCrowdsaleImpl is TimedCrowdsale { - - constructor ( - uint256 openingTime, - uint256 closingTime, - uint256 rate, - address wallet, - IERC20 token - ) - public - Crowdsale(rate, wallet, token) - TimedCrowdsale(openingTime, closingTime) - { - } - + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + public + Crowdsale(rate, wallet, token) + TimedCrowdsale(openingTime, closingTime) + {} } diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 7b5b72102..5ab46c511 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -6,70 +6,67 @@ pragma solidity ^0.4.24; * functions, this simplifies the implementation of "user permissions". */ contract Ownable { - address private _owner; + address private _owner; - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() internal { - _owner = msg.sender; - emit OwnershipTransferred(address(0), _owner); - } + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor () internal { + _owner = msg.sender; + emit OwnershipTransferred(address(0), _owner); + } - /** - * @return the address of the owner. - */ - function owner() public view returns(address) { - return _owner; - } + /** + * @return the address of the owner. + */ + function owner() public view returns (address) { + return _owner; + } - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(isOwner()); + _; + } - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns(bool) { - return msg.sender == _owner; - } + /** + * @return true if `msg.sender` is the owner of the contract. + */ + function isOwner() public view returns (bool) { + return msg.sender == _owner; + } - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } + /** + * @dev Allows the current owner to relinquish control of the contract. + * @notice Renouncing to ownership will leave the contract without an owner. + * It will not be possible to call the functions with the `onlyOwner` + * modifier anymore. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + _transferOwnership(newOwner); + } - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } + /** + * @dev Transfers control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function _transferOwnership(address newOwner) internal { + require(newOwner != address(0)); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } } diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index 67d2250d5..e12cf3cb4 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -5,42 +5,42 @@ pragma solidity ^0.4.24; * @dev A Secondary contract can only be used by its primary account (the one that created it) */ contract Secondary { - address private _primary; + address private _primary; - event PrimaryTransferred( - address recipient - ); + event PrimaryTransferred( + address recipient + ); - /** - * @dev Sets the primary account to the one that is creating the Secondary contract. - */ - constructor() internal { - _primary = msg.sender; - emit PrimaryTransferred(_primary); - } + /** + * @dev Sets the primary account to the one that is creating the Secondary contract. + */ + constructor () internal { + _primary = msg.sender; + emit PrimaryTransferred(_primary); + } - /** - * @dev Reverts if called from any account other than the primary. - */ - modifier onlyPrimary() { - require(msg.sender == _primary); - _; - } + /** + * @dev Reverts if called from any account other than the primary. + */ + modifier onlyPrimary() { + require(msg.sender == _primary); + _; + } - /** - * @return the address of the primary. - */ - function primary() public view returns (address) { - return _primary; - } - - /** - * @dev Transfers contract to a new primary. - * @param recipient The address of new primary. - */ - function transferPrimary(address recipient) public onlyPrimary { - require(recipient != address(0)); - _primary = recipient; - emit PrimaryTransferred(_primary); - } + /** + * @return the address of the primary. + */ + function primary() public view returns (address) { + return _primary; + } + + /** + * @dev Transfers contract to a new primary. + * @param recipient The address of new primary. + */ + function transferPrimary(address recipient) public onlyPrimary { + require(recipient != address(0)); + _primary = recipient; + emit PrimaryTransferred(_primary); + } } diff --git a/contracts/payment/PaymentSplitter.sol b/contracts/payment/PaymentSplitter.sol index 0a1b470ef..0b07e62ba 100644 --- a/contracts/payment/PaymentSplitter.sol +++ b/contracts/payment/PaymentSplitter.sol @@ -8,109 +8,105 @@ import "../math/SafeMath.sol"; * of people and split proportionately to some number of shares they own. */ contract PaymentSplitter { - using SafeMath for uint256; + using SafeMath for uint256; - event PayeeAdded(address account, uint256 shares); - event PaymentReleased(address to, uint256 amount); - event PaymentReceived(address from, uint256 amount); + event PayeeAdded(address account, uint256 shares); + event PaymentReleased(address to, uint256 amount); + event PaymentReceived(address from, uint256 amount); - uint256 private _totalShares; - uint256 private _totalReleased; + uint256 private _totalShares; + uint256 private _totalReleased; - mapping(address => uint256) private _shares; - mapping(address => uint256) private _released; - address[] private _payees; + mapping(address => uint256) private _shares; + mapping(address => uint256) private _released; + address[] private _payees; - /** - * @dev Constructor - */ - constructor(address[] payees, uint256[] shares) public payable { - require(payees.length == shares.length); - require(payees.length > 0); + /** + * @dev Constructor + */ + constructor (address[] payees, uint256[] shares) public payable { + require(payees.length == shares.length); + require(payees.length > 0); - for (uint256 i = 0; i < payees.length; i++) { - _addPayee(payees[i], shares[i]); + for (uint256 i = 0; i < payees.length; i++) { + _addPayee(payees[i], shares[i]); + } } - } - /** - * @dev payable fallback - */ - function () external payable { - emit PaymentReceived(msg.sender, msg.value); - } + /** + * @dev payable fallback + */ + function () external payable { + emit PaymentReceived(msg.sender, msg.value); + } - /** - * @return the total shares of the contract. - */ - function totalShares() public view returns(uint256) { - return _totalShares; - } + /** + * @return the total shares of the contract. + */ + function totalShares() public view returns (uint256) { + return _totalShares; + } - /** - * @return the total amount already released. - */ - function totalReleased() public view returns(uint256) { - return _totalReleased; - } + /** + * @return the total amount already released. + */ + function totalReleased() public view returns (uint256) { + return _totalReleased; + } - /** - * @return the shares of an account. - */ - function shares(address account) public view returns(uint256) { - return _shares[account]; - } + /** + * @return the shares of an account. + */ + function shares(address account) public view returns (uint256) { + return _shares[account]; + } - /** - * @return the amount already released to an account. - */ - function released(address account) public view returns(uint256) { - return _released[account]; - } + /** + * @return the amount already released to an account. + */ + function released(address account) public view returns (uint256) { + return _released[account]; + } - /** - * @return the address of a payee. - */ - function payee(uint256 index) public view returns(address) { - return _payees[index]; - } + /** + * @return the address of a payee. + */ + function payee(uint256 index) public view returns (address) { + return _payees[index]; + } - /** - * @dev Release one of the payee's proportional payment. - * @param account Whose payments will be released. - */ - function release(address account) public { - require(_shares[account] > 0); + /** + * @dev Release one of the payee's proportional payment. + * @param account Whose payments will be released. + */ + function release(address account) public { + require(_shares[account] > 0); - uint256 totalReceived = address(this).balance.add(_totalReleased); - uint256 payment = totalReceived.mul( - _shares[account]).div( - _totalShares).sub( - _released[account] - ); + uint256 totalReceived = address(this).balance.add(_totalReleased); + uint256 payment = totalReceived.mul(_shares[account]).div(_totalShares).sub(_released[account]); - require(payment != 0); + require(payment != 0); - _released[account] = _released[account].add(payment); - _totalReleased = _totalReleased.add(payment); + _released[account] = _released[account].add(payment); + _totalReleased = _totalReleased.add(payment); - account.transfer(payment); - emit PaymentReleased(account, payment); - } + account.transfer(payment); + emit PaymentReleased(account, payment); + } - /** - * @dev Add a new payee to the contract. - * @param account The address of the payee to add. - * @param shares_ The number of shares owned by the payee. - */ - function _addPayee(address account, uint256 shares_) private { - require(account != address(0)); - require(shares_ > 0); - require(_shares[account] == 0); + /** + * @dev Add a new payee to the contract. + * @param account The address of the payee to add. + * @param shares_ The number of shares owned by the payee. + */ + function _addPayee(address account, uint256 shares_) private { + require(account != address(0)); + require(shares_ > 0); + require(_shares[account] == 0); - _payees.push(account); - _shares[account] = shares_; - _totalShares = _totalShares.add(shares_); - emit PayeeAdded(account, shares_); - } + _payees.push(account); + _shares[account] = shares_; + _totalShares = _totalShares.add(shares_); + emit PayeeAdded(account, shares_); + } } diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index f6d7e2c1e..9517638be 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -8,34 +8,34 @@ import "./escrow/Escrow.sol"; * contract and use _asyncTransfer instead of send or transfer. */ contract PullPayment { - Escrow private _escrow; + Escrow private _escrow; - constructor() internal { - _escrow = new Escrow(); - } + constructor () internal { + _escrow = new Escrow(); + } - /** - * @dev Withdraw accumulated balance. - * @param payee Whose balance will be withdrawn. - */ - function withdrawPayments(address payee) public { - _escrow.withdraw(payee); - } + /** + * @dev Withdraw accumulated balance. + * @param payee Whose balance will be withdrawn. + */ + function withdrawPayments(address payee) public { + _escrow.withdraw(payee); + } - /** - * @dev Returns the credit owed to an address. - * @param dest The creditor's address. - */ - function payments(address dest) public view returns (uint256) { - return _escrow.depositsOf(dest); - } + /** + * @dev Returns the credit owed to an address. + * @param dest The creditor's address. + */ + function payments(address dest) public view returns (uint256) { + return _escrow.depositsOf(dest); + } - /** - * @dev Called by the payer to store the sent amount as credit to be pulled. - * @param dest The destination address of the funds. - * @param amount The amount to transfer. - */ - function _asyncTransfer(address dest, uint256 amount) internal { - _escrow.deposit.value(amount)(dest); - } + /** + * @dev Called by the payer to store the sent amount as credit to be pulled. + * @param dest The destination address of the funds. + * @param amount The amount to transfer. + */ + function _asyncTransfer(address dest, uint256 amount) internal { + _escrow.deposit.value(amount)(dest); + } } diff --git a/contracts/payment/escrow/ConditionalEscrow.sol b/contracts/payment/escrow/ConditionalEscrow.sol index c3f63ee37..8697b4f93 100644 --- a/contracts/payment/escrow/ConditionalEscrow.sol +++ b/contracts/payment/escrow/ConditionalEscrow.sol @@ -8,15 +8,15 @@ import "./Escrow.sol"; * @dev Intended usage: See Escrow.sol. Same usage guidelines apply here. */ contract ConditionalEscrow is Escrow { - /** - * @dev Returns whether an address is allowed to withdraw their funds. To be - * implemented by derived contracts. - * @param payee The destination address of the funds. - */ - function withdrawalAllowed(address payee) public view returns (bool); + /** + * @dev Returns whether an address is allowed to withdraw their funds. To be + * implemented by derived contracts. + * @param payee The destination address of the funds. + */ + function withdrawalAllowed(address payee) public view returns (bool); - function withdraw(address payee) public { - require(withdrawalAllowed(payee)); - super.withdraw(payee); - } + function withdraw(address payee) public { + require(withdrawalAllowed(payee)); + super.withdraw(payee); + } } diff --git a/contracts/payment/escrow/Escrow.sol b/contracts/payment/escrow/Escrow.sol index b2f2a85ee..088df38ff 100644 --- a/contracts/payment/escrow/Escrow.sol +++ b/contracts/payment/escrow/Escrow.sol @@ -16,39 +16,39 @@ import "../../ownership/Secondary.sol"; * to the escrow's deposit and withdraw. */ contract Escrow is Secondary { - using SafeMath for uint256; + using SafeMath for uint256; - event Deposited(address indexed payee, uint256 weiAmount); - event Withdrawn(address indexed payee, uint256 weiAmount); + event Deposited(address indexed payee, uint256 weiAmount); + event Withdrawn(address indexed payee, uint256 weiAmount); - mapping(address => uint256) private _deposits; + mapping(address => uint256) private _deposits; - function depositsOf(address payee) public view returns (uint256) { - return _deposits[payee]; - } + function depositsOf(address payee) public view returns (uint256) { + return _deposits[payee]; + } - /** - * @dev Stores the sent amount as credit to be withdrawn. - * @param payee The destination address of the funds. - */ - function deposit(address payee) public onlyPrimary payable { - uint256 amount = msg.value; - _deposits[payee] = _deposits[payee].add(amount); + /** + * @dev Stores the sent amount as credit to be withdrawn. + * @param payee The destination address of the funds. + */ + function deposit(address payee) public onlyPrimary payable { + uint256 amount = msg.value; + _deposits[payee] = _deposits[payee].add(amount); - emit Deposited(payee, amount); - } + emit Deposited(payee, amount); + } - /** - * @dev Withdraw accumulated balance for a payee. - * @param payee The address whose funds will be withdrawn and transferred to. - */ - function withdraw(address payee) public onlyPrimary { - uint256 payment = _deposits[payee]; + /** + * @dev Withdraw accumulated balance for a payee. + * @param payee The address whose funds will be withdrawn and transferred to. + */ + function withdraw(address payee) public onlyPrimary { + uint256 payment = _deposits[payee]; - _deposits[payee] = 0; + _deposits[payee] = 0; - payee.transfer(payment); + payee.transfer(payment); - emit Withdrawn(payee, payment); - } + emit Withdrawn(payee, payment); + } } diff --git a/contracts/payment/escrow/RefundEscrow.sol b/contracts/payment/escrow/RefundEscrow.sol index a776a81c8..67f00e580 100644 --- a/contracts/payment/escrow/RefundEscrow.sol +++ b/contracts/payment/escrow/RefundEscrow.sol @@ -14,78 +14,78 @@ import "./ConditionalEscrow.sol"; * RefundableCrowdsale contract for an example of RefundEscrow’s use. */ contract RefundEscrow is ConditionalEscrow { - enum State { Active, Refunding, Closed } + enum State { Active, Refunding, Closed } - event RefundsClosed(); - event RefundsEnabled(); + event RefundsClosed(); + event RefundsEnabled(); - State private _state; - address private _beneficiary; + State private _state; + address private _beneficiary; - /** - * @dev Constructor. - * @param beneficiary The beneficiary of the deposits. - */ - constructor(address beneficiary) public { - require(beneficiary != address(0)); - _beneficiary = beneficiary; - _state = State.Active; - } + /** + * @dev Constructor. + * @param beneficiary The beneficiary of the deposits. + */ + constructor (address beneficiary) public { + require(beneficiary != address(0)); + _beneficiary = beneficiary; + _state = State.Active; + } - /** - * @return the current state of the escrow. - */ - function state() public view returns (State) { - return _state; - } + /** + * @return the current state of the escrow. + */ + function state() public view returns (State) { + return _state; + } - /** - * @return the beneficiary of the escrow. - */ - function beneficiary() public view returns (address) { - return _beneficiary; - } + /** + * @return the beneficiary of the escrow. + */ + function beneficiary() public view returns (address) { + return _beneficiary; + } - /** - * @dev Stores funds that may later be refunded. - * @param refundee The address funds will be sent to if a refund occurs. - */ - function deposit(address refundee) public payable { - require(_state == State.Active); - super.deposit(refundee); - } + /** + * @dev Stores funds that may later be refunded. + * @param refundee The address funds will be sent to if a refund occurs. + */ + function deposit(address refundee) public payable { + require(_state == State.Active); + super.deposit(refundee); + } - /** - * @dev Allows for the beneficiary to withdraw their funds, rejecting - * further deposits. - */ - function close() public onlyPrimary { - require(_state == State.Active); - _state = State.Closed; - emit RefundsClosed(); - } + /** + * @dev Allows for the beneficiary to withdraw their funds, rejecting + * further deposits. + */ + function close() public onlyPrimary { + require(_state == State.Active); + _state = State.Closed; + emit RefundsClosed(); + } - /** - * @dev Allows for refunds to take place, rejecting further deposits. - */ - function enableRefunds() public onlyPrimary { - require(_state == State.Active); - _state = State.Refunding; - emit RefundsEnabled(); - } + /** + * @dev Allows for refunds to take place, rejecting further deposits. + */ + function enableRefunds() public onlyPrimary { + require(_state == State.Active); + _state = State.Refunding; + emit RefundsEnabled(); + } - /** - * @dev Withdraws the beneficiary's funds. - */ - function beneficiaryWithdraw() public { - require(_state == State.Closed); - _beneficiary.transfer(address(this).balance); - } + /** + * @dev Withdraws the beneficiary's funds. + */ + function beneficiaryWithdraw() public { + require(_state == State.Closed); + _beneficiary.transfer(address(this).balance); + } - /** - * @dev Returns whether refundees can withdraw their deposits (be refunded). - */ - function withdrawalAllowed(address payee) public view returns (bool) { - return _state == State.Refunding; - } + /** + * @dev Returns whether refundees can withdraw their deposits (be refunded). + */ + function withdrawalAllowed(address payee) public view returns (bool) { + return _state == State.Refunding; + } } diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 5c550539f..abb43b74d 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -11,196 +11,167 @@ import "../../math/SafeMath.sol"; * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol */ contract ERC20 is IERC20 { - using SafeMath for uint256; + using SafeMath for uint256; - mapping (address => uint256) private _balances; + mapping (address => uint256) private _balances; - mapping (address => mapping (address => uint256)) private _allowed; + mapping (address => mapping (address => uint256)) private _allowed; - uint256 private _totalSupply; + uint256 private _totalSupply; - /** - * @dev Total number of tokens in existence - */ - function totalSupply() public view returns (uint256) { - return _totalSupply; - } + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return _totalSupply; + } - /** - * @dev Gets the balance of the specified address. - * @param owner The address to query the balance of. - * @return An uint256 representing the amount owned by the passed address. - */ - function balanceOf(address owner) public view returns (uint256) { - return _balances[owner]; - } + /** + * @dev Gets the balance of the specified address. + * @param owner The address to query the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address owner) public view returns (uint256) { + return _balances[owner]; + } - /** - * @dev Function to check the amount of tokens that an owner allowed to a spender. - * @param owner address The address which owns the funds. - * @param spender address The address which will spend the funds. - * @return A uint256 specifying the amount of tokens still available for the spender. - */ - function allowance( - address owner, - address spender - ) - public - view - returns (uint256) - { - return _allowed[owner][spender]; - } + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param owner address The address which owns the funds. + * @param spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance(address owner, address spender) public view returns (uint256) { + return _allowed[owner][spender]; + } - /** - * @dev Transfer token for a specified address - * @param to The address to transfer to. - * @param value The amount to be transferred. - */ - function transfer(address to, uint256 value) public returns (bool) { - _transfer(msg.sender, to, value); - return true; - } + /** + * @dev Transfer token for a specified address + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function transfer(address to, uint256 value) public returns (bool) { + _transfer(msg.sender, to, value); + return true; + } - /** - * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. - * Beware that changing an allowance with this method brings the risk that someone may use both the old - * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this - * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * @param spender The address which will spend the funds. - * @param value The amount of tokens to be spent. - */ - function approve(address spender, uint256 value) public returns (bool) { - require(spender != address(0)); + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param spender The address which will spend the funds. + * @param value The amount of tokens to be spent. + */ + function approve(address spender, uint256 value) public returns (bool) { + require(spender != address(0)); - _allowed[msg.sender][spender] = value; - emit Approval(msg.sender, spender, value); - return true; - } + _allowed[msg.sender][spender] = value; + emit Approval(msg.sender, spender, value); + return true; + } - /** - * @dev Transfer tokens from one address to another - * @param from address The address which you want to send tokens from - * @param to address The address which you want to transfer to - * @param value uint256 the amount of tokens to be transferred - */ - function transferFrom( - address from, - address to, - uint256 value - ) - public - returns (bool) - { - _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); - _transfer(from, to, value); - return true; - } + /** + * @dev Transfer tokens from one address to another + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 the amount of tokens to be transferred + */ + function transferFrom(address from, address to, uint256 value) public returns (bool) { + _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); + _transfer(from, to, value); + return true; + } - /** - * @dev Increase the amount of tokens that an owner allowed to a spender. - * approve should be called when allowed_[_spender] == 0. To increment - * allowed value is better to use this function to avoid 2 calls (and wait until - * the first transaction is mined) - * From MonolithDAO Token.sol - * @param spender The address which will spend the funds. - * @param addedValue The amount of tokens to increase the allowance by. - */ - function increaseAllowance( - address spender, - uint256 addedValue - ) - public - returns (bool) - { - require(spender != address(0)); + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed_[_spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param spender The address which will spend the funds. + * @param addedValue The amount of tokens to increase the allowance by. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + require(spender != address(0)); - _allowed[msg.sender][spender] = ( - _allowed[msg.sender][spender].add(addedValue)); - emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); - return true; - } + _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue); + emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); + return true; + } - /** - * @dev Decrease the amount of tokens that an owner allowed to a spender. - * approve should be called when allowed_[_spender] == 0. To decrement - * allowed value is better to use this function to avoid 2 calls (and wait until - * the first transaction is mined) - * From MonolithDAO Token.sol - * @param spender The address which will spend the funds. - * @param subtractedValue The amount of tokens to decrease the allowance by. - */ - function decreaseAllowance( - address spender, - uint256 subtractedValue - ) - public - returns (bool) - { - require(spender != address(0)); + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed_[_spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param spender The address which will spend the funds. + * @param subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + require(spender != address(0)); - _allowed[msg.sender][spender] = ( - _allowed[msg.sender][spender].sub(subtractedValue)); - emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); - return true; - } + _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue); + emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); + return true; + } - /** - * @dev Transfer token for a specified addresses - * @param from The address to transfer from. - * @param to The address to transfer to. - * @param value The amount to be transferred. - */ - function _transfer(address from, address to, uint256 value) internal { - require(to != address(0)); + /** + * @dev Transfer token for a specified addresses + * @param from The address to transfer from. + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function _transfer(address from, address to, uint256 value) internal { + require(to != address(0)); - _balances[from] = _balances[from].sub(value); - _balances[to] = _balances[to].add(value); - emit Transfer(from, to, value); - } + _balances[from] = _balances[from].sub(value); + _balances[to] = _balances[to].add(value); + emit Transfer(from, to, value); + } - /** - * @dev Internal function that mints an amount of the token and assigns it to - * an account. This encapsulates the modification of balances such that the - * proper events are emitted. - * @param account The account that will receive the created tokens. - * @param value The amount that will be created. - */ - function _mint(address account, uint256 value) internal { - require(account != address(0)); + /** + * @dev Internal function that mints an amount of the token and assigns it to + * an account. This encapsulates the modification of balances such that the + * proper events are emitted. + * @param account The account that will receive the created tokens. + * @param value The amount that will be created. + */ + function _mint(address account, uint256 value) internal { + require(account != address(0)); - _totalSupply = _totalSupply.add(value); - _balances[account] = _balances[account].add(value); - emit Transfer(address(0), account, value); - } + _totalSupply = _totalSupply.add(value); + _balances[account] = _balances[account].add(value); + emit Transfer(address(0), account, value); + } - /** - * @dev Internal function that burns an amount of the token of a given - * account. - * @param account The account whose tokens will be burnt. - * @param value The amount that will be burnt. - */ - function _burn(address account, uint256 value) internal { - require(account != address(0)); + /** + * @dev Internal function that burns an amount of the token of a given + * account. + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burn(address account, uint256 value) internal { + require(account != address(0)); - _totalSupply = _totalSupply.sub(value); - _balances[account] = _balances[account].sub(value); - emit Transfer(account, address(0), value); - } + _totalSupply = _totalSupply.sub(value); + _balances[account] = _balances[account].sub(value); + emit Transfer(account, address(0), value); + } - /** - * @dev Internal function that burns an amount of the token of a given - * account, deducting from the sender's allowance for said account. Uses the - * internal burn function. - * @param account The account whose tokens will be burnt. - * @param value The amount that will be burnt. - */ - function _burnFrom(address account, uint256 value) internal { - // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, - // this function needs to emit an event with the updated approval. - _allowed[account][msg.sender] = _allowed[account][msg.sender].sub( - value); - _burn(account, value); - } + /** + * @dev Internal function that burns an amount of the token of a given + * account, deducting from the sender's allowance for said account. Uses the + * internal burn function. + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burnFrom(address account, uint256 value) internal { + // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, + // this function needs to emit an event with the updated approval. + _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value); + _burn(account, value); + } } diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index ba4a2ccbe..9f1120016 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -7,21 +7,20 @@ import "./ERC20.sol"; * @dev Token that can be irreversibly burned (destroyed). */ contract ERC20Burnable is ERC20 { + /** + * @dev Burns a specific amount of tokens. + * @param value The amount of token to be burned. + */ + function burn(uint256 value) public { + _burn(msg.sender, value); + } - /** - * @dev Burns a specific amount of tokens. - * @param value The amount of token to be burned. - */ - function burn(uint256 value) public { - _burn(msg.sender, value); - } - - /** - * @dev Burns a specific amount of tokens from the target address and decrements allowance - * @param from address The address which you want to send tokens from - * @param value uint256 The amount of token to be burned - */ - function burnFrom(address from, uint256 value) public { - _burnFrom(from, value); - } + /** + * @dev Burns a specific amount of tokens from the target address and decrements allowance + * @param from address The address which you want to send tokens from + * @param value uint256 The amount of token to be burned + */ + function burnFrom(address from, uint256 value) public { + _burnFrom(from, value); + } } diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index a80dd491c..2d6c35326 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -7,25 +7,22 @@ import "./ERC20Mintable.sol"; * @dev Mintable token with a token cap. */ contract ERC20Capped is ERC20Mintable { + uint256 private _cap; - uint256 private _cap; + constructor (uint256 cap) public { + require(cap > 0); + _cap = cap; + } - constructor(uint256 cap) - public - { - require(cap > 0); - _cap = cap; - } + /** + * @return the cap for the token minting. + */ + function cap() public view returns (uint256) { + return _cap; + } - /** - * @return the cap for the token minting. - */ - function cap() public view returns(uint256) { - return _cap; - } - - function _mint(address account, uint256 value) internal { - require(totalSupply().add(value) <= _cap); - super._mint(account, value); - } + function _mint(address account, uint256 value) internal { + require(totalSupply().add(value) <= _cap); + super._mint(account, value); + } } diff --git a/contracts/token/ERC20/ERC20Detailed.sol b/contracts/token/ERC20/ERC20Detailed.sol index 706dbfc46..02f1648da 100644 --- a/contracts/token/ERC20/ERC20Detailed.sol +++ b/contracts/token/ERC20/ERC20Detailed.sol @@ -9,34 +9,34 @@ import "./IERC20.sol"; * just as on Ethereum all the operations are done in wei. */ contract ERC20Detailed is IERC20 { - string private _name; - string private _symbol; - uint8 private _decimals; + string private _name; + string private _symbol; + uint8 private _decimals; - constructor(string name, string symbol, uint8 decimals) public { - _name = name; - _symbol = symbol; - _decimals = decimals; - } + constructor (string name, string symbol, uint8 decimals) public { + _name = name; + _symbol = symbol; + _decimals = decimals; + } - /** - * @return the name of the token. - */ - function name() public view returns(string) { - return _name; - } + /** + * @return the name of the token. + */ + function name() public view returns (string) { + return _name; + } - /** - * @return the symbol of the token. - */ - function symbol() public view returns(string) { - return _symbol; - } + /** + * @return the symbol of the token. + */ + function symbol() public view returns (string) { + return _symbol; + } - /** - * @return the number of decimals of the token. - */ - function decimals() public view returns(uint8) { - return _decimals; - } + /** + * @return the number of decimals of the token. + */ + function decimals() public view returns (uint8) { + return _decimals; + } } diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index eb01f06e7..ec30caa48 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -8,21 +8,14 @@ import "../../access/roles/MinterRole.sol"; * @dev ERC20 minting logic */ contract ERC20Mintable is ERC20, MinterRole { - /** - * @dev Function to mint tokens - * @param to The address that will receive the minted tokens. - * @param value The amount of tokens to mint. - * @return A boolean that indicates if the operation was successful. - */ - function mint( - address to, - uint256 value - ) - public - onlyMinter - returns (bool) - { - _mint(to, value); - return true; - } + /** + * @dev Function to mint tokens + * @param to The address that will receive the minted tokens. + * @param value The amount of tokens to mint. + * @return A boolean that indicates if the operation was successful. + */ + function mint(address to, uint256 value) public onlyMinter returns (bool) { + _mint(to, value); + return true; + } } diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index 8e6aa881f..b3947d589 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -8,60 +8,23 @@ import "../../lifecycle/Pausable.sol"; * @dev ERC20 modified with pausable transfers. **/ contract ERC20Pausable is ERC20, Pausable { + function transfer(address to, uint256 value) public whenNotPaused returns (bool) { + return super.transfer(to, value); + } - function transfer( - address to, - uint256 value - ) - public - whenNotPaused - returns (bool) - { - return super.transfer(to, value); - } + function transferFrom(address from,address to, uint256 value) public whenNotPaused returns (bool) { + return super.transferFrom(from, to, value); + } - function transferFrom( - address from, - address to, - uint256 value - ) - public - whenNotPaused - returns (bool) - { - return super.transferFrom(from, to, value); - } + function approve(address spender, uint256 value) public whenNotPaused returns (bool) { + return super.approve(spender, value); + } - function approve( - address spender, - uint256 value - ) - public - whenNotPaused - returns (bool) - { - return super.approve(spender, value); - } + function increaseAllowance(address spender, uint addedValue) public whenNotPaused returns (bool success) { + return super.increaseAllowance(spender, addedValue); + } - function increaseAllowance( - address spender, - uint addedValue - ) - public - whenNotPaused - returns (bool success) - { - return super.increaseAllowance(spender, addedValue); - } - - function decreaseAllowance( - address spender, - uint subtractedValue - ) - public - whenNotPaused - returns (bool success) - { - return super.decreaseAllowance(spender, subtractedValue); - } + function decreaseAllowance(address spender, uint subtractedValue) public whenNotPaused returns (bool success) { + return super.decreaseAllowance(spender, subtractedValue); + } } diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index 37e5a447c..7c44280f0 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -5,30 +5,19 @@ pragma solidity ^0.4.24; * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 { - function totalSupply() external view returns (uint256); + function totalSupply() external view returns (uint256); - function balanceOf(address who) external view returns (uint256); + function balanceOf(address who) external view returns (uint256); - function allowance(address owner, address spender) - external view returns (uint256); + function allowance(address owner, address spender) external view returns (uint256); - function transfer(address to, uint256 value) external returns (bool); + function transfer(address to, uint256 value) external returns (bool); - function approve(address spender, uint256 value) - external returns (bool); + function approve(address spender, uint256 value) external returns (bool); - function transferFrom(address from, address to, uint256 value) - external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); - event Transfer( - address indexed from, - address indexed to, - uint256 value - ); + event Transfer(address indexed from, address indexed to, uint256 value); - event Approval( - address indexed owner, - address indexed spender, - uint256 value - ); + event Approval(address indexed owner, address indexed spender, uint256 value); } diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index 2774afa08..adb217e0b 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -10,63 +10,31 @@ import "../../math/SafeMath.sol"; * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { + using SafeMath for uint256; - using SafeMath for uint256; + function safeTransfer(IERC20 token, address to, uint256 value) internal { + require(token.transfer(to, value)); + } - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) - internal - { - require(token.transfer(to, value)); - } + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + require(token.transferFrom(from, to, value)); + } - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) - internal - { - require(token.transferFrom(from, to, value)); - } + function safeApprove(IERC20 token, address spender, uint256 value) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require((value == 0) || (token.allowance(msg.sender, spender) == 0)); + require(token.approve(spender, value)); + } - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) - internal - { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require((value == 0) || (token.allowance(msg.sender, spender) == 0)); - require(token.approve(spender, value)); - } + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).add(value); + require(token.approve(spender, newAllowance)); + } - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) - internal - { - uint256 newAllowance = token.allowance(address(this), spender).add(value); - require(token.approve(spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) - internal - { - uint256 newAllowance = token.allowance(address(this), spender).sub(value); - require(token.approve(spender, newAllowance)); - } + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).sub(value); + require(token.approve(spender, newAllowance)); + } } diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index 55903482b..a69680507 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -8,62 +8,56 @@ import "./SafeERC20.sol"; * beneficiary to extract the tokens after a given release time */ contract TokenTimelock { - using SafeERC20 for IERC20; + using SafeERC20 for IERC20; - // ERC20 basic token contract being held - IERC20 private _token; + // ERC20 basic token contract being held + IERC20 private _token; - // beneficiary of tokens after they are released - address private _beneficiary; + // beneficiary of tokens after they are released + address private _beneficiary; - // timestamp when token release is enabled - uint256 private _releaseTime; + // timestamp when token release is enabled + uint256 private _releaseTime; - constructor( - IERC20 token, - address beneficiary, - uint256 releaseTime - ) - public - { - // solium-disable-next-line security/no-block-members - require(releaseTime > block.timestamp); - _token = token; - _beneficiary = beneficiary; - _releaseTime = releaseTime; - } + constructor (IERC20 token, address beneficiary, uint256 releaseTime) public { + // solium-disable-next-line security/no-block-members + require(releaseTime > block.timestamp); + _token = token; + _beneficiary = beneficiary; + _releaseTime = releaseTime; + } - /** - * @return the token being held. - */ - function token() public view returns(IERC20) { - return _token; - } + /** + * @return the token being held. + */ + function token() public view returns (IERC20) { + return _token; + } - /** - * @return the beneficiary of the tokens. - */ - function beneficiary() public view returns(address) { - return _beneficiary; - } + /** + * @return the beneficiary of the tokens. + */ + function beneficiary() public view returns (address) { + return _beneficiary; + } - /** - * @return the time when the tokens are released. - */ - function releaseTime() public view returns(uint256) { - return _releaseTime; - } + /** + * @return the time when the tokens are released. + */ + function releaseTime() public view returns (uint256) { + return _releaseTime; + } - /** - * @notice Transfers tokens held by timelock to beneficiary. - */ - function release() public { - // solium-disable-next-line security/no-block-members - require(block.timestamp >= _releaseTime); + /** + * @notice Transfers tokens held by timelock to beneficiary. + */ + function release() public { + // solium-disable-next-line security/no-block-members + require(block.timestamp >= _releaseTime); - uint256 amount = _token.balanceOf(address(this)); - require(amount > 0); + uint256 amount = _token.balanceOf(address(this)); + require(amount > 0); - _token.safeTransfer(_beneficiary, amount); - } + _token.safeTransfer(_beneficiary, amount); + } } diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index ec0763b96..d64c97b32 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -11,320 +11,272 @@ import "../../introspection/ERC165.sol"; * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721 is ERC165, IERC721 { + using SafeMath for uint256; + using Address for address; - using SafeMath for uint256; - using Address for address; + // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` + bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; + // Mapping from token ID to owner + mapping (uint256 => address) private _tokenOwner; - // Mapping from token ID to owner - mapping (uint256 => address) private _tokenOwner; + // Mapping from token ID to approved address + mapping (uint256 => address) private _tokenApprovals; - // Mapping from token ID to approved address - mapping (uint256 => address) private _tokenApprovals; + // Mapping from owner to number of owned token + mapping (address => uint256) private _ownedTokensCount; - // Mapping from owner to number of owned token - mapping (address => uint256) private _ownedTokensCount; + // Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) private _operatorApprovals; - // Mapping from owner to operator approvals - mapping (address => mapping (address => bool)) private _operatorApprovals; + bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; + /* + * 0x80ac58cd === + * bytes4(keccak256('balanceOf(address)')) ^ + * bytes4(keccak256('ownerOf(uint256)')) ^ + * bytes4(keccak256('approve(address,uint256)')) ^ + * bytes4(keccak256('getApproved(uint256)')) ^ + * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ + * bytes4(keccak256('isApprovedForAll(address,address)')) ^ + * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) + */ - bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; - /* - * 0x80ac58cd === - * bytes4(keccak256('balanceOf(address)')) ^ - * bytes4(keccak256('ownerOf(uint256)')) ^ - * bytes4(keccak256('approve(address,uint256)')) ^ - * bytes4(keccak256('getApproved(uint256)')) ^ - * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ - * bytes4(keccak256('isApprovedForAll(address,address)')) ^ - * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) - */ - - constructor() - public - { - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(_InterfaceId_ERC721); - } - - /** - * @dev Gets the balance of the specified address - * @param owner address to query the balance of - * @return uint256 representing the amount owned by the passed address - */ - function balanceOf(address owner) public view returns (uint256) { - require(owner != address(0)); - return _ownedTokensCount[owner]; - } - - /** - * @dev Gets the owner of the specified token ID - * @param tokenId uint256 ID of the token to query the owner of - * @return owner address currently marked as the owner of the given token ID - */ - function ownerOf(uint256 tokenId) public view returns (address) { - address owner = _tokenOwner[tokenId]; - require(owner != address(0)); - return owner; - } - - /** - * @dev Approves another address to transfer the given token ID - * The zero address indicates there is no approved address. - * There can only be one approved address per token at a given time. - * Can only be called by the token owner or an approved operator. - * @param to address to be approved for the given token ID - * @param tokenId uint256 ID of the token to be approved - */ - function approve(address to, uint256 tokenId) public { - address owner = ownerOf(tokenId); - require(to != owner); - require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); - - _tokenApprovals[tokenId] = to; - emit Approval(owner, to, tokenId); - } - - /** - * @dev Gets the approved address for a token ID, or zero if no address set - * Reverts if the token ID does not exist. - * @param tokenId uint256 ID of the token to query the approval of - * @return address currently approved for the given token ID - */ - function getApproved(uint256 tokenId) public view returns (address) { - require(_exists(tokenId)); - return _tokenApprovals[tokenId]; - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param to operator address to set the approval - * @param approved representing the status of the approval to be set - */ - function setApprovalForAll(address to, bool approved) public { - require(to != msg.sender); - _operatorApprovals[msg.sender][to] = approved; - emit ApprovalForAll(msg.sender, to, approved); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param owner owner address which you want to query the approval of - * @param operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address owner, - address operator - ) - public - view - returns (bool) - { - return _operatorApprovals[owner][operator]; - } - - /** - * @dev Transfers the ownership of a given token ID to another address - * Usage of this method is discouraged, use `safeTransferFrom` whenever possible - * Requires the msg sender to be the owner, approved, or operator - * @param from current owner of the token - * @param to address to receive the ownership of the given token ID - * @param tokenId uint256 ID of the token to be transferred - */ - function transferFrom( - address from, - address to, - uint256 tokenId - ) - public - { - require(_isApprovedOrOwner(msg.sender, tokenId)); - require(to != address(0)); - - _clearApproval(from, tokenId); - _removeTokenFrom(from, tokenId); - _addTokenTo(to, tokenId); - - emit Transfer(from, to, tokenId); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * - * Requires the msg sender to be the owner, approved, or operator - * @param from current owner of the token - * @param to address to receive the ownership of the given token ID - * @param tokenId uint256 ID of the token to be transferred - */ - function safeTransferFrom( - address from, - address to, - uint256 tokenId - ) - public - { - // solium-disable-next-line arg-overflow - safeTransferFrom(from, to, tokenId, ""); - } - - /** - * @dev Safely transfers the ownership of a given token ID to another address - * If the target address is a contract, it must implement `onERC721Received`, - * which is called upon a safe transfer, and return the magic value - * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, - * the transfer is reverted. - * Requires the msg sender to be the owner, approved, or operator - * @param from current owner of the token - * @param to address to receive the ownership of the given token ID - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes data to send along with a safe transfer check - */ - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes _data - ) - public - { - transferFrom(from, to, tokenId); - // solium-disable-next-line arg-overflow - require(_checkOnERC721Received(from, to, tokenId, _data)); - } - - /** - * @dev Returns whether the specified token exists - * @param tokenId uint256 ID of the token to query the existence of - * @return whether the token exists - */ - function _exists(uint256 tokenId) internal view returns (bool) { - address owner = _tokenOwner[tokenId]; - return owner != address(0); - } - - /** - * @dev Returns whether the given spender can transfer a given token ID - * @param spender address of the spender to query - * @param tokenId uint256 ID of the token to be transferred - * @return bool whether the msg.sender is approved for the given token ID, - * is an operator of the owner, or is the owner of the token - */ - function _isApprovedOrOwner( - address spender, - uint256 tokenId - ) - internal - view - returns (bool) - { - address owner = ownerOf(tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace - return ( - spender == owner || - getApproved(tokenId) == spender || - isApprovedForAll(owner, spender) - ); - } - - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param to The address that will own the minted token - * @param tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address to, uint256 tokenId) internal { - require(to != address(0)); - _addTokenTo(to, tokenId); - emit Transfer(address(0), to, tokenId); - } - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address owner, uint256 tokenId) internal { - _clearApproval(owner, tokenId); - _removeTokenFrom(owner, tokenId); - emit Transfer(owner, address(0), tokenId); - } - - /** - * @dev Internal function to add a token ID to the list of a given address - * Note that this function is left internal to make ERC721Enumerable possible, but is not - * intended to be called by custom derived contracts: in particular, it emits no Transfer event. - * @param to address representing the new owner of the given token ID - * @param tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function _addTokenTo(address to, uint256 tokenId) internal { - require(_tokenOwner[tokenId] == address(0)); - _tokenOwner[tokenId] = to; - _ownedTokensCount[to] = _ownedTokensCount[to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * Note that this function is left internal to make ERC721Enumerable possible, but is not - * intended to be called by custom derived contracts: in particular, it emits no Transfer event, - * and doesn't clear approvals. - * @param from address representing the previous owner of the given token ID - * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function _removeTokenFrom(address from, uint256 tokenId) internal { - require(ownerOf(tokenId) == from); - _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); - _tokenOwner[tokenId] = address(0); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes _data - ) - internal - returns (bool) - { - if (!to.isContract()) { - return true; + constructor () public { + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(_InterfaceId_ERC721); } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, from, tokenId, _data); - return (retval == _ERC721_RECEIVED); - } - /** - * @dev Private function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param owner owner of the token - * @param tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(address owner, uint256 tokenId) private { - require(ownerOf(tokenId) == owner); - if (_tokenApprovals[tokenId] != address(0)) { - _tokenApprovals[tokenId] = address(0); + /** + * @dev Gets the balance of the specified address + * @param owner address to query the balance of + * @return uint256 representing the amount owned by the passed address + */ + function balanceOf(address owner) public view returns (uint256) { + require(owner != address(0)); + return _ownedTokensCount[owner]; + } + + /** + * @dev Gets the owner of the specified token ID + * @param tokenId uint256 ID of the token to query the owner of + * @return owner address currently marked as the owner of the given token ID + */ + function ownerOf(uint256 tokenId) public view returns (address) { + address owner = _tokenOwner[tokenId]; + require(owner != address(0)); + return owner; + } + + /** + * @dev Approves another address to transfer the given token ID + * The zero address indicates there is no approved address. + * There can only be one approved address per token at a given time. + * Can only be called by the token owner or an approved operator. + * @param to address to be approved for the given token ID + * @param tokenId uint256 ID of the token to be approved + */ + function approve(address to, uint256 tokenId) public { + address owner = ownerOf(tokenId); + require(to != owner); + require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); + + _tokenApprovals[tokenId] = to; + emit Approval(owner, to, tokenId); + } + + /** + * @dev Gets the approved address for a token ID, or zero if no address set + * Reverts if the token ID does not exist. + * @param tokenId uint256 ID of the token to query the approval of + * @return address currently approved for the given token ID + */ + function getApproved(uint256 tokenId) public view returns (address) { + require(_exists(tokenId)); + return _tokenApprovals[tokenId]; + } + + /** + * @dev Sets or unsets the approval of a given operator + * An operator is allowed to transfer all tokens of the sender on their behalf + * @param to operator address to set the approval + * @param approved representing the status of the approval to be set + */ + function setApprovalForAll(address to, bool approved) public { + require(to != msg.sender); + _operatorApprovals[msg.sender][to] = approved; + emit ApprovalForAll(msg.sender, to, approved); + } + + /** + * @dev Tells whether an operator is approved by a given owner + * @param owner owner address which you want to query the approval of + * @param operator operator address which you want to query the approval of + * @return bool whether the given operator is approved by the given owner + */ + function isApprovedForAll(address owner, address operator) public view returns (bool) { + return _operatorApprovals[owner][operator]; + } + + /** + * @dev Transfers the ownership of a given token ID to another address + * Usage of this method is discouraged, use `safeTransferFrom` whenever possible + * Requires the msg sender to be the owner, approved, or operator + * @param from current owner of the token + * @param to address to receive the ownership of the given token ID + * @param tokenId uint256 ID of the token to be transferred + */ + function transferFrom(address from, address to, uint256 tokenId) public { + require(_isApprovedOrOwner(msg.sender, tokenId)); + require(to != address(0)); + + _clearApproval(from, tokenId); + _removeTokenFrom(from, tokenId); + _addTokenTo(to, tokenId); + + emit Transfer(from, to, tokenId); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * + * Requires the msg sender to be the owner, approved, or operator + * @param from current owner of the token + * @param to address to receive the ownership of the given token ID + * @param tokenId uint256 ID of the token to be transferred + */ + function safeTransferFrom(address from, address to, uint256 tokenId) public { + // solium-disable-next-line arg-overflow + safeTransferFrom(from, to, tokenId, ""); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * Requires the msg sender to be the owner, approved, or operator + * @param from current owner of the token + * @param to address to receive the ownership of the given token ID + * @param tokenId uint256 ID of the token to be transferred + * @param _data bytes data to send along with a safe transfer check + */ + function safeTransferFrom(address from, address to, uint256 tokenId, bytes _data) public { + transferFrom(from, to, tokenId); + // solium-disable-next-line arg-overflow + require(_checkOnERC721Received(from, to, tokenId, _data)); + } + + /** + * @dev Returns whether the specified token exists + * @param tokenId uint256 ID of the token to query the existence of + * @return whether the token exists + */ + function _exists(uint256 tokenId) internal view returns (bool) { + address owner = _tokenOwner[tokenId]; + return owner != address(0); + } + + /** + * @dev Returns whether the given spender can transfer a given token ID + * @param spender address of the spender to query + * @param tokenId uint256 ID of the token to be transferred + * @return bool whether the msg.sender is approved for the given token ID, + * is an operator of the owner, or is the owner of the token + */ + function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { + address owner = ownerOf(tokenId); + // Disable solium check because of + // https://github.com/duaraghav8/Solium/issues/175 + // solium-disable-next-line operator-whitespace + return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); + } + + /** + * @dev Internal function to mint a new token + * Reverts if the given token ID already exists + * @param to The address that will own the minted token + * @param tokenId uint256 ID of the token to be minted by the msg.sender + */ + function _mint(address to, uint256 tokenId) internal { + require(to != address(0)); + _addTokenTo(to, tokenId); + emit Transfer(address(0), to, tokenId); + } + + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param tokenId uint256 ID of the token being burned by the msg.sender + */ + function _burn(address owner, uint256 tokenId) internal { + _clearApproval(owner, tokenId); + _removeTokenFrom(owner, tokenId); + emit Transfer(owner, address(0), tokenId); + } + + /** + * @dev Internal function to add a token ID to the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event. + * @param to address representing the new owner of the given token ID + * @param tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function _addTokenTo(address to, uint256 tokenId) internal { + require(_tokenOwner[tokenId] == address(0)); + _tokenOwner[tokenId] = to; + _ownedTokensCount[to] = _ownedTokensCount[to].add(1); + } + + /** + * @dev Internal function to remove a token ID from the list of a given address + * Note that this function is left internal to make ERC721Enumerable possible, but is not + * intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. + * @param from address representing the previous owner of the given token ID + * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function _removeTokenFrom(address from, uint256 tokenId) internal { + require(ownerOf(tokenId) == from); + _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); + _tokenOwner[tokenId] = address(0); + } + + /** + * @dev Internal function to invoke `onERC721Received` on a target address + * The call is not executed if the target address is not a contract + * @param from address representing the previous owner of the given token ID + * @param to target address that will receive the tokens + * @param tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return whether the call correctly returned the expected magic value + */ + function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes _data) internal returns (bool) { + if (!to.isContract()) { + return true; + } + + bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data); + return (retval == _ERC721_RECEIVED); + } + + /** + * @dev Private function to clear current approval of a given token ID + * Reverts if the given address is not indeed the owner of the token + * @param owner owner of the token + * @param tokenId uint256 ID of the token to be transferred + */ + function _clearApproval(address owner, uint256 tokenId) private { + require(ownerOf(tokenId) == owner); + if (_tokenApprovals[tokenId] != address(0)) { + _tokenApprovals[tokenId] = address(0); + } } - } } diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index 71f3bcdd1..2d8732b38 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -7,15 +7,12 @@ import "./ERC721.sol"; * @dev ERC721 Token that can be irreversibly burned (destroyed). */ contract ERC721Burnable is ERC721 { - - /** - * @dev Burns a specific ERC721 token. - * @param tokenId uint256 id of the ERC721 token to be burned. - */ - function burn(uint256 tokenId) - public - { - require(_isApprovedOrOwner(msg.sender, tokenId)); - _burn(ownerOf(tokenId), tokenId); - } + /** + * @dev Burns a specific ERC721 token. + * @param tokenId uint256 id of the ERC721 token to be burned. + */ + function burn(uint256 tokenId) public { + require(_isApprovedOrOwner(msg.sender, tokenId)); + _burn(ownerOf(tokenId), tokenId); + } } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index 234307755..ff8c1b9ee 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -9,146 +9,139 @@ import "../../introspection/ERC165.sol"; * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { - // Mapping from owner to list of owned token IDs - mapping(address => uint256[]) private _ownedTokens; + // Mapping from owner to list of owned token IDs + mapping(address => uint256[]) private _ownedTokens; - // Mapping from token ID to index of the owner tokens list - mapping(uint256 => uint256) private _ownedTokensIndex; + // Mapping from token ID to index of the owner tokens list + mapping(uint256 => uint256) private _ownedTokensIndex; - // Array with all token ids, used for enumeration - uint256[] private _allTokens; + // Array with all token ids, used for enumeration + uint256[] private _allTokens; - // Mapping from token id to position in the allTokens array - mapping(uint256 => uint256) private _allTokensIndex; + // Mapping from token id to position in the allTokens array + mapping(uint256 => uint256) private _allTokensIndex; - bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; - /** - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ + bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; + /** + * 0x780e9d63 === + * bytes4(keccak256('totalSupply()')) ^ + * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ + * bytes4(keccak256('tokenByIndex(uint256)')) + */ - /** - * @dev Constructor function - */ - constructor() public { - // register the supported interface to conform to ERC721 via ERC165 - _registerInterface(_InterfaceId_ERC721Enumerable); - } + /** + * @dev Constructor function + */ + constructor () public { + // register the supported interface to conform to ERC721 via ERC165 + _registerInterface(_InterfaceId_ERC721Enumerable); + } - /** - * @dev Gets the token ID at a given index of the tokens list of the requested owner - * @param owner address owning the tokens list to be accessed - * @param index uint256 representing the index to be accessed of the requested tokens list - * @return uint256 token ID at the given index of the tokens list owned by the requested address - */ - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) - public - view - returns (uint256) - { - require(index < balanceOf(owner)); - return _ownedTokens[owner][index]; - } + /** + * @dev Gets the token ID at a given index of the tokens list of the requested owner + * @param owner address owning the tokens list to be accessed + * @param index uint256 representing the index to be accessed of the requested tokens list + * @return uint256 token ID at the given index of the tokens list owned by the requested address + */ + function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { + require(index < balanceOf(owner)); + return _ownedTokens[owner][index]; + } - /** - * @dev Gets the total amount of tokens stored by the contract - * @return uint256 representing the total amount of tokens - */ - function totalSupply() public view returns (uint256) { - return _allTokens.length; - } + /** + * @dev Gets the total amount of tokens stored by the contract + * @return uint256 representing the total amount of tokens + */ + function totalSupply() public view returns (uint256) { + return _allTokens.length; + } - /** - * @dev Gets the token ID at a given index of all the tokens in this contract - * Reverts if the index is greater or equal to the total number of tokens - * @param index uint256 representing the index to be accessed of the tokens list - * @return uint256 token ID at the given index of the tokens list - */ - function tokenByIndex(uint256 index) public view returns (uint256) { - require(index < totalSupply()); - return _allTokens[index]; - } + /** + * @dev Gets the token ID at a given index of all the tokens in this contract + * Reverts if the index is greater or equal to the total number of tokens + * @param index uint256 representing the index to be accessed of the tokens list + * @return uint256 token ID at the given index of the tokens list + */ + function tokenByIndex(uint256 index) public view returns (uint256) { + require(index < totalSupply()); + return _allTokens[index]; + } - /** - * @dev Internal function to add a token ID to the list of a given address - * This function is internal due to language limitations, see the note in ERC721.sol. - * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. - * @param to address representing the new owner of the given token ID - * @param tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function _addTokenTo(address to, uint256 tokenId) internal { - super._addTokenTo(to, tokenId); - uint256 length = _ownedTokens[to].length; - _ownedTokens[to].push(tokenId); - _ownedTokensIndex[tokenId] = length; - } + /** + * @dev Internal function to add a token ID to the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. + * @param to address representing the new owner of the given token ID + * @param tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function _addTokenTo(address to, uint256 tokenId) internal { + super._addTokenTo(to, tokenId); + uint256 length = _ownedTokens[to].length; + _ownedTokens[to].push(tokenId); + _ownedTokensIndex[tokenId] = length; + } - /** - * @dev Internal function to remove a token ID from the list of a given address - * This function is internal due to language limitations, see the note in ERC721.sol. - * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, - * and doesn't clear approvals. - * @param from address representing the previous owner of the given token ID - * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function _removeTokenFrom(address from, uint256 tokenId) internal { - super._removeTokenFrom(from, tokenId); + /** + * @dev Internal function to remove a token ID from the list of a given address + * This function is internal due to language limitations, see the note in ERC721.sol. + * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, + * and doesn't clear approvals. + * @param from address representing the previous owner of the given token ID + * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function _removeTokenFrom(address from, uint256 tokenId) internal { + super._removeTokenFrom(from, tokenId); - // To prevent a gap in the array, we store the last token in the index of the token to delete, and - // then delete the last slot. - uint256 tokenIndex = _ownedTokensIndex[tokenId]; - uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); - uint256 lastToken = _ownedTokens[from][lastTokenIndex]; + // To prevent a gap in the array, we store the last token in the index of the token to delete, and + // then delete the last slot. + uint256 tokenIndex = _ownedTokensIndex[tokenId]; + uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); + uint256 lastToken = _ownedTokens[from][lastTokenIndex]; - _ownedTokens[from][tokenIndex] = lastToken; - // This also deletes the contents at the last position of the array - _ownedTokens[from].length--; + _ownedTokens[from][tokenIndex] = lastToken; + // This also deletes the contents at the last position of the array + _ownedTokens[from].length--; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list + // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to + // be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping + // the lastToken to the first position, and then dropping the element placed in the last position of the list - _ownedTokensIndex[tokenId] = 0; - _ownedTokensIndex[lastToken] = tokenIndex; - } + _ownedTokensIndex[tokenId] = 0; + _ownedTokensIndex[lastToken] = tokenIndex; + } - /** - * @dev Internal function to mint a new token - * Reverts if the given token ID already exists - * @param to address the beneficiary that will own the minted token - * @param tokenId uint256 ID of the token to be minted by the msg.sender - */ - function _mint(address to, uint256 tokenId) internal { - super._mint(to, tokenId); + /** + * @dev Internal function to mint a new token + * Reverts if the given token ID already exists + * @param to address the beneficiary that will own the minted token + * @param tokenId uint256 ID of the token to be minted by the msg.sender + */ + function _mint(address to, uint256 tokenId) internal { + super._mint(to, tokenId); - _allTokensIndex[tokenId] = _allTokens.length; - _allTokens.push(tokenId); - } + _allTokensIndex[tokenId] = _allTokens.length; + _allTokens.push(tokenId); + } - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param owner owner of the token to burn - * @param tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address owner, uint256 tokenId) internal { - super._burn(owner, tokenId); + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param owner owner of the token to burn + * @param tokenId uint256 ID of the token being burned by the msg.sender + */ + function _burn(address owner, uint256 tokenId) internal { + super._burn(owner, tokenId); - // Reorg all tokens array - uint256 tokenIndex = _allTokensIndex[tokenId]; - uint256 lastTokenIndex = _allTokens.length.sub(1); - uint256 lastToken = _allTokens[lastTokenIndex]; + // Reorg all tokens array + uint256 tokenIndex = _allTokensIndex[tokenId]; + uint256 lastTokenIndex = _allTokens.length.sub(1); + uint256 lastToken = _allTokens[lastTokenIndex]; - _allTokens[tokenIndex] = lastToken; - _allTokens[lastTokenIndex] = 0; + _allTokens[tokenIndex] = lastToken; + _allTokens[lastTokenIndex] = 0; - _allTokens.length--; - _allTokensIndex[tokenId] = 0; - _allTokensIndex[lastToken] = tokenIndex; - } + _allTokens.length--; + _allTokensIndex[tokenId] = 0; + _allTokensIndex[lastToken] = tokenIndex; + } } diff --git a/contracts/token/ERC721/ERC721Full.sol b/contracts/token/ERC721/ERC721Full.sol index 293637501..1c964ea8e 100644 --- a/contracts/token/ERC721/ERC721Full.sol +++ b/contracts/token/ERC721/ERC721Full.sol @@ -11,8 +11,5 @@ import "./ERC721Metadata.sol"; * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata { - constructor(string name, string symbol) ERC721Metadata(name, symbol) - public - { - } + constructor (string name, string symbol) ERC721Metadata(name, symbol) public {} } diff --git a/contracts/token/ERC721/ERC721Holder.sol b/contracts/token/ERC721/ERC721Holder.sol index cf0e9ce55..87480b9fa 100644 --- a/contracts/token/ERC721/ERC721Holder.sol +++ b/contracts/token/ERC721/ERC721Holder.sol @@ -3,15 +3,7 @@ pragma solidity ^0.4.24; import "./IERC721Receiver.sol"; contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes - ) - public - returns(bytes4) - { - return this.onERC721Received.selector; - } + function onERC721Received(address, address, uint256, bytes) public returns (bytes4) { + return this.onERC721Received.selector; + } } diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index bd1105188..522b626e8 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -5,83 +5,83 @@ import "./IERC721Metadata.sol"; import "../../introspection/ERC165.sol"; contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { - // Token name - string private _name; + // Token name + string private _name; - // Token symbol - string private _symbol; + // Token symbol + string private _symbol; - // Optional mapping for token URIs - mapping(uint256 => string) private _tokenURIs; + // Optional mapping for token URIs + mapping(uint256 => string) private _tokenURIs; - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; - /** - * 0x5b5e139f === - * bytes4(keccak256('name()')) ^ - * bytes4(keccak256('symbol()')) ^ - * bytes4(keccak256('tokenURI(uint256)')) - */ + bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; + /** + * 0x5b5e139f === + * bytes4(keccak256('name()')) ^ + * bytes4(keccak256('symbol()')) ^ + * bytes4(keccak256('tokenURI(uint256)')) + */ - /** - * @dev Constructor function - */ - constructor(string name, string symbol) public { - _name = name; - _symbol = symbol; + /** + * @dev Constructor function + */ + constructor (string name, string symbol) public { + _name = name; + _symbol = symbol; - // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Metadata); - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string) { - return _name; - } - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string) { - return _symbol; - } - - /** - * @dev Returns an URI for a given token ID - * Throws if the token ID does not exist. May return an empty string. - * @param tokenId uint256 ID of the token to query - */ - function tokenURI(uint256 tokenId) external view returns (string) { - require(_exists(tokenId)); - return _tokenURIs[tokenId]; - } - - /** - * @dev Internal function to set the token URI for a given token - * Reverts if the token ID does not exist - * @param tokenId uint256 ID of the token to set its URI - * @param uri string URI to assign - */ - function _setTokenURI(uint256 tokenId, string uri) internal { - require(_exists(tokenId)); - _tokenURIs[tokenId] = uri; - } - - /** - * @dev Internal function to burn a specific token - * Reverts if the token does not exist - * @param owner owner of the token to burn - * @param tokenId uint256 ID of the token being burned by the msg.sender - */ - function _burn(address owner, uint256 tokenId) internal { - super._burn(owner, tokenId); - - // Clear metadata (if any) - if (bytes(_tokenURIs[tokenId]).length != 0) { - delete _tokenURIs[tokenId]; + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(InterfaceId_ERC721Metadata); + } + + /** + * @dev Gets the token name + * @return string representing the token name + */ + function name() external view returns (string) { + return _name; + } + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string) { + return _symbol; + } + + /** + * @dev Returns an URI for a given token ID + * Throws if the token ID does not exist. May return an empty string. + * @param tokenId uint256 ID of the token to query + */ + function tokenURI(uint256 tokenId) external view returns (string) { + require(_exists(tokenId)); + return _tokenURIs[tokenId]; + } + + /** + * @dev Internal function to set the token URI for a given token + * Reverts if the token ID does not exist + * @param tokenId uint256 ID of the token to set its URI + * @param uri string URI to assign + */ + function _setTokenURI(uint256 tokenId, string uri) internal { + require(_exists(tokenId)); + _tokenURIs[tokenId] = uri; + } + + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param owner owner of the token to burn + * @param tokenId uint256 ID of the token being burned by the msg.sender + */ + function _burn(address owner, uint256 tokenId) internal { + super._burn(owner, tokenId); + + // Clear metadata (if any) + if (bytes(_tokenURIs[tokenId]).length != 0) { + delete _tokenURIs[tokenId]; + } } - } } diff --git a/contracts/token/ERC721/ERC721MetadataMintable.sol b/contracts/token/ERC721/ERC721MetadataMintable.sol index 95a9f2124..6e20f83a3 100644 --- a/contracts/token/ERC721/ERC721MetadataMintable.sol +++ b/contracts/token/ERC721/ERC721MetadataMintable.sol @@ -9,24 +9,16 @@ import "../../access/roles/MinterRole.sol"; * @dev ERC721 minting logic with metadata */ contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { - /** - * @dev Function to mint tokens - * @param to The address that will receive the minted tokens. - * @param tokenId The token id to mint. - * @param tokenURI The token URI of the minted token. - * @return A boolean that indicates if the operation was successful. - */ - function mintWithTokenURI( - address to, - uint256 tokenId, - string tokenURI - ) - public - onlyMinter - returns (bool) - { - _mint(to, tokenId); - _setTokenURI(tokenId, tokenURI); - return true; - } + /** + * @dev Function to mint tokens + * @param to The address that will receive the minted tokens. + * @param tokenId The token id to mint. + * @param tokenURI The token URI of the minted token. + * @return A boolean that indicates if the operation was successful. + */ + function mintWithTokenURI(address to, uint256 tokenId, string tokenURI) public onlyMinter returns (bool) { + _mint(to, tokenId); + _setTokenURI(tokenId, tokenURI); + return true; + } } diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index 74b7b0186..48a7f2095 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -8,21 +8,14 @@ import "../../access/roles/MinterRole.sol"; * @dev ERC721 minting logic */ contract ERC721Mintable is ERC721, MinterRole { - /** - * @dev Function to mint tokens - * @param to The address that will receive the minted tokens. - * @param tokenId The token id to mint. - * @return A boolean that indicates if the operation was successful. - */ - function mint( - address to, - uint256 tokenId - ) - public - onlyMinter - returns (bool) - { - _mint(to, tokenId); - return true; - } + /** + * @dev Function to mint tokens + * @param to The address that will receive the minted tokens. + * @param tokenId The token id to mint. + * @return A boolean that indicates if the operation was successful. + */ + function mint(address to, uint256 tokenId) public onlyMinter returns (bool) { + _mint(to, tokenId); + return true; + } } diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/ERC721Pausable.sol index c66d9da1f..0fb2ef3b5 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/ERC721Pausable.sol @@ -8,34 +8,15 @@ import "../../lifecycle/Pausable.sol"; * @dev ERC721 modified with pausable transfers. **/ contract ERC721Pausable is ERC721, Pausable { - function approve( - address to, - uint256 tokenId - ) - public - whenNotPaused - { - super.approve(to, tokenId); - } + function approve(address to, uint256 tokenId) public whenNotPaused { + super.approve(to, tokenId); + } - function setApprovalForAll( - address to, - bool approved - ) - public - whenNotPaused - { - super.setApprovalForAll(to, approved); - } + function setApprovalForAll(address to, bool approved) public whenNotPaused { + super.setApprovalForAll(to, approved); + } - function transferFrom( - address from, - address to, - uint256 tokenId - ) - public - whenNotPaused - { - super.transferFrom(from, to, tokenId); - } + function transferFrom(address from, address to, uint256 tokenId) public whenNotPaused { + super.transferFrom(from, to, tokenId); + } } diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index 24bc6a242..003802182 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -7,43 +7,21 @@ import "../../introspection/IERC165.sol"; * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721 is IERC165 { + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); + function balanceOf(address owner) public view returns (uint256 balance); + function ownerOf(uint256 tokenId) public view returns (address owner); - function balanceOf(address owner) public view returns (uint256 balance); - function ownerOf(uint256 tokenId) public view returns (address owner); + function approve(address to, uint256 tokenId) public; + function getApproved(uint256 tokenId) public view returns (address operator); - function approve(address to, uint256 tokenId) public; - function getApproved(uint256 tokenId) - public view returns (address operator); + function setApprovalForAll(address operator, bool _approved) public; + function isApprovedForAll(address owner, address operator) public view returns (bool); - function setApprovalForAll(address operator, bool _approved) public; - function isApprovedForAll(address owner, address operator) - public view returns (bool); + function transferFrom(address from, address to, uint256 tokenId) public; + function safeTransferFrom(address from, address to, uint256 tokenId) public; - function transferFrom(address from, address to, uint256 tokenId) public; - function safeTransferFrom(address from, address to, uint256 tokenId) - public; - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes data - ) - public; + function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) public; } diff --git a/contracts/token/ERC721/IERC721Enumerable.sol b/contracts/token/ERC721/IERC721Enumerable.sol index b772f2507..06a50ed1b 100644 --- a/contracts/token/ERC721/IERC721Enumerable.sol +++ b/contracts/token/ERC721/IERC721Enumerable.sol @@ -7,14 +7,8 @@ import "./IERC721.sol"; * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Enumerable is IERC721 { - function totalSupply() public view returns (uint256); - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) - public - view - returns (uint256 tokenId); + function totalSupply() public view returns (uint256); + function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId); - function tokenByIndex(uint256 index) public view returns (uint256); + function tokenByIndex(uint256 index) public view returns (uint256); } diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index 15b5ae4c6..2d7d1b249 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -7,7 +7,7 @@ import "./IERC721.sol"; * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Metadata is IERC721 { - function name() external view returns (string); - function symbol() external view returns (string); - function tokenURI(uint256 tokenId) external view returns (string); + function name() external view returns (string); + function symbol() external view returns (string); + function tokenURI(uint256 tokenId) external view returns (string); } diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol index e692f7e2c..7c360d7b4 100644 --- a/contracts/token/ERC721/IERC721Receiver.sol +++ b/contracts/token/ERC721/IERC721Receiver.sol @@ -6,26 +6,19 @@ pragma solidity ^0.4.24; * from ERC721 asset contracts. */ contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes data - ) - public - returns(bytes4); + /** + * @notice Handle the receipt of an NFT + * @dev The ERC721 smart contract calls this function on the recipient + * after a `safeTransfer`. This function MUST return the function selector, + * otherwise the caller will revert the transaction. The selector to be + * returned can be obtained as `this.onERC721Received.selector`. This + * function MAY throw to revert and reject the transfer. + * Note: the ERC721 contract address is always the message sender. + * @param operator The address which called `safeTransferFrom` function + * @param from The address which previously owned the token + * @param tokenId The NFT identifier which is being transferred + * @param data Additional data with no specified format + * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + */ + function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public returns (bytes4); } diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index 92a43ff9c..c44dfa17f 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -4,25 +4,23 @@ pragma solidity ^0.4.24; * Utility library of inline functions on addresses */ library Address { - - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param account address of the account to check - * @return whether the target address is a contract - */ - function isContract(address account) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solium-disable-next-line security/no-inline-assembly - assembly { size := extcodesize(account) } - return size > 0; - } - + /** + * Returns whether the target address is a contract + * @dev This function will return false if invoked during the constructor of a contract, + * as the code is not actually created until after the constructor finishes. + * @param account address of the account to check + * @return whether the target address is a contract + */ + function isContract(address account) internal view returns (bool) { + uint256 size; + // XXX Currently there is no better way to check if there is a contract in an address + // than to check the size of the code at that address. + // See https://ethereum.stackexchange.com/a/14016/36603 + // for more details about how this works. + // TODO Check this again before the Serenity release, because all addresses will be + // contracts then. + // solium-disable-next-line security/no-inline-assembly + assembly { size := extcodesize(account) } + return size > 0; + } } diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol index 6882ea995..7d8e29339 100644 --- a/contracts/utils/Arrays.sol +++ b/contracts/utils/Arrays.sol @@ -8,49 +8,41 @@ import "../math/Math.sol"; * @dev Utility library of inline array functions */ library Arrays { + /** + * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted + * array to find index of the element value. If element is found then returns it's index otherwise + * it returns index of first element which is grater than searched value. If searched element is + * bigger than any array element function then returns first index after last element (i.e. all + * values inside the array are smaller than the target). Complexity O(log n). + * @param array The array sorted in ascending order. + * @param element The element's value to be find. + * @return The calculated index value. Returns 0 for empty array. + */ + function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + if (array.length == 0) { + return 0; + } - /** - * @dev Upper bound search function which is kind of binary search algoritm. It searches sorted - * array to find index of the element value. If element is found then returns it's index otherwise - * it returns index of first element which is grater than searched value. If searched element is - * bigger than any array element function then returns first index after last element (i.e. all - * values inside the array are smaller than the target). Complexity O(log n). - * @param array The array sorted in ascending order. - * @param element The element's value to be find. - * @return The calculated index value. Returns 0 for empty array. - */ - function findUpperBound( - uint256[] storage array, - uint256 element - ) - internal - view - returns (uint256) - { - if (array.length == 0) { - return 0; + uint256 low = 0; + uint256 high = array.length; + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds down (it does integer division with truncation). + if (array[mid] > element) { + high = mid; + } else { + low = mid + 1; + } + } + + // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. + if (low > 0 && array[low - 1] == element) { + return low - 1; + } else { + return low; + } } - - uint256 low = 0; - uint256 high = array.length; - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds down (it does integer division with truncation). - if (array[mid] > element) { - high = mid; - } else { - low = mid + 1; - } - } - - // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. - if (low > 0 && array[low - 1] == element) { - return low - 1; - } else { - return low; - } - } } diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 7a2895da2..40af0f688 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -7,28 +7,26 @@ pragma solidity ^0.4.24; * mark it `external`. */ contract ReentrancyGuard { + /// @dev counter to allow mutex lock with only one SSTORE operation + uint256 private _guardCounter; - /// @dev counter to allow mutex lock with only one SSTORE operation - uint256 private _guardCounter; - - constructor() internal { - // The counter starts at one to prevent changing it from zero to a non-zero - // value, which is a more expensive operation. - _guardCounter = 1; - } - - /** - * @dev Prevents a contract from calling itself, directly or indirectly. - * Calling a `nonReentrant` function from another `nonReentrant` - * function is not supported. It is possible to prevent this from happening - * by making the `nonReentrant` function external, and make it call a - * `private` function that does the actual work. - */ - modifier nonReentrant() { - _guardCounter += 1; - uint256 localCounter = _guardCounter; - _; - require(localCounter == _guardCounter); - } + constructor () internal { + // The counter starts at one to prevent changing it from zero to a non-zero + // value, which is a more expensive operation. + _guardCounter = 1; + } + /** + * @dev Prevents a contract from calling itself, directly or indirectly. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and make it call a + * `private` function that does the actual work. + */ + modifier nonReentrant() { + _guardCounter += 1; + uint256 localCounter = _guardCounter; + _; + require(localCounter == _guardCounter); + } } From b9793abec6fe21590ac472386fa4b7d1ecdab977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 26 Nov 2018 15:41:39 -0300 Subject: [PATCH 163/205] balanceDifference tests and application (#1514) * Added balanceDifference tests. * Added balanceDifference tests. * Now using balanceDifference in all (most) tests. * Fixed typo. --- test/crowdsale/AllowanceCrowdsale.test.js | 9 +++--- test/crowdsale/Crowdsale.test.js | 16 +++++----- test/crowdsale/MintedCrowdsale.behavior.js | 9 +++--- test/crowdsale/RefundableCrowdsale.test.js | 8 ++--- test/examples/SampleCrowdsale.test.js | 29 ++++++++----------- .../{balanceDiff.js => balanceDifference.js} | 4 +-- test/helpers/test/balanceDifference.test.js | 22 ++++++++++++++ test/payment/PullPayment.test.js | 15 ++++------ test/payment/escrow/Escrow.behavior.js | 13 ++++----- test/payment/escrow/RefundEscrow.test.js | 18 +++++------- 10 files changed, 73 insertions(+), 70 deletions(-) rename test/helpers/{balanceDiff.js => balanceDifference.js} (70%) create mode 100644 test/helpers/test/balanceDifference.test.js diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 413d25544..5f4c0ad30 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -1,7 +1,7 @@ const expectEvent = require('../helpers/expectEvent'); const { ether } = require('../helpers/ether'); const shouldFail = require('../helpers/shouldFail'); -const { ethGetBalance } = require('../helpers/web3'); +const { balanceDifference } = require('../helpers/balanceDifference'); const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -56,10 +56,9 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW }); it('should forward funds to wallet', async function () { - const pre = await ethGetBalance(wallet); - await this.crowdsale.sendTransaction({ value, from: investor }); - const post = await ethGetBalance(wallet); - post.minus(pre).should.be.bignumber.equal(value); + (await balanceDifference(wallet, () => + this.crowdsale.sendTransaction({ value, from: investor })) + ).should.be.bignumber.equal(value); }); }); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index b7528e4e9..c2646db9b 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -1,7 +1,7 @@ const expectEvent = require('../helpers/expectEvent'); const shouldFail = require('../helpers/shouldFail'); +const { balanceDifference } = require('../helpers/balanceDifference'); const { ether } = require('../helpers/ether'); -const { ethGetBalance } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); const BigNumber = web3.BigNumber; @@ -97,10 +97,9 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('should forward funds to wallet', async function () { - const pre = await ethGetBalance(wallet); - await this.crowdsale.sendTransaction({ value, from: investor }); - const post = await ethGetBalance(wallet); - post.minus(pre).should.be.bignumber.equal(value); + (await balanceDifference(wallet, () => + this.crowdsale.sendTransaction({ value, from: investor })) + ).should.be.bignumber.equal(value); }); }); @@ -121,10 +120,9 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { }); it('should forward funds to wallet', async function () { - const pre = await ethGetBalance(wallet); - await this.crowdsale.buyTokens(investor, { value, from: purchaser }); - const post = await ethGetBalance(wallet); - post.minus(pre).should.be.bignumber.equal(value); + (await balanceDifference(wallet, () => + this.crowdsale.buyTokens(investor, { value, from: purchaser })) + ).should.be.bignumber.equal(value); }); }); }); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index ab8dc8259..e58d54aa6 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -1,5 +1,5 @@ const expectEvent = require('../helpers/expectEvent'); -const { ethGetBalance } = require('../helpers/web3'); +const { balanceDifference } = require('../helpers/balanceDifference'); const BigNumber = web3.BigNumber; @@ -35,10 +35,9 @@ function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate }); it('should forward funds to wallet', async function () { - const pre = await ethGetBalance(wallet); - await this.crowdsale.sendTransaction({ value, from: investor }); - const post = await ethGetBalance(wallet); - post.minus(pre).should.be.bignumber.equal(value); + (await balanceDifference(wallet, () => + this.crowdsale.sendTransaction({ value, from: investor })) + ).should.be.bignumber.equal(value); }); }); }); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 6b863abad..8472b87f2 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,5 +1,6 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); +const { balanceDifference } = require('../helpers/balanceDifference'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); const { ethGetBalance } = require('../helpers/web3'); @@ -75,10 +76,9 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon }); it('refunds', async function () { - const pre = await ethGetBalance(investor); - await this.crowdsale.claimRefund(investor, { gasPrice: 0 }); - const post = await ethGetBalance(investor); - post.minus(pre).should.be.bignumber.equal(lessThanGoal); + (await balanceDifference(investor, () => + this.crowdsale.claimRefund(investor, { gasPrice: 0 })) + ).should.be.bignumber.equal(lessThanGoal); }); }); }); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index da367c970..da0bf1f7c 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -2,7 +2,7 @@ const { ether } = require('../helpers/ether'); const { advanceBlock } = require('../helpers/advanceToBlock'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const { ethGetBalance } = require('../helpers/web3'); +const { balanceDifference } = require('../helpers/balanceDifference'); const BigNumber = web3.BigNumber; @@ -82,26 +82,21 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { await time.increaseTo(this.openingTime); await this.crowdsale.send(GOAL); - const beforeFinalization = await ethGetBalance(wallet); - await time.increaseTo(this.afterClosingTime); - await this.crowdsale.finalize({ from: owner }); - const afterFinalization = await ethGetBalance(wallet); - - afterFinalization.minus(beforeFinalization).should.be.bignumber.equal(GOAL); + (await balanceDifference(wallet, async () => { + await time.increaseTo(this.afterClosingTime); + await this.crowdsale.finalize({ from: owner }); + })).should.be.bignumber.equal(GOAL); }); it('should allow refunds if the goal is not reached', async function () { - const balanceBeforeInvestment = await ethGetBalance(investor); + (await balanceDifference(investor, async () => { + await time.increaseTo(this.openingTime); + await this.crowdsale.sendTransaction({ value: ether(1), from: investor, gasPrice: 0 }); + await time.increaseTo(this.afterClosingTime); - await time.increaseTo(this.openingTime); - await this.crowdsale.sendTransaction({ value: ether(1), from: investor, gasPrice: 0 }); - await time.increaseTo(this.afterClosingTime); - - await this.crowdsale.finalize({ from: owner }); - await this.crowdsale.claimRefund(investor, { gasPrice: 0 }); - - const balanceAfterRefund = await ethGetBalance(investor); - balanceBeforeInvestment.should.be.bignumber.equal(balanceAfterRefund); + await this.crowdsale.finalize({ from: owner }); + await this.crowdsale.claimRefund(investor, { gasPrice: 0 }); + })).should.be.bignumber.equal(0); }); describe('when goal > cap', function () { diff --git a/test/helpers/balanceDiff.js b/test/helpers/balanceDifference.js similarity index 70% rename from test/helpers/balanceDiff.js rename to test/helpers/balanceDifference.js index 8f88ba400..883d7df49 100644 --- a/test/helpers/balanceDiff.js +++ b/test/helpers/balanceDifference.js @@ -1,6 +1,6 @@ -async function balanceDifference (account, promise) { +async function balanceDifference (account, promiseFunc) { const balanceBefore = web3.eth.getBalance(account); - await promise(); + await promiseFunc(); const balanceAfter = web3.eth.getBalance(account); return balanceAfter.minus(balanceBefore); } diff --git a/test/helpers/test/balanceDifference.test.js b/test/helpers/test/balanceDifference.test.js new file mode 100644 index 000000000..e4eddc7f5 --- /dev/null +++ b/test/helpers/test/balanceDifference.test.js @@ -0,0 +1,22 @@ +const { balanceDifference } = require('../balanceDifference'); +const { sendEther } = require('../sendTransaction'); +const { ether } = require('../ether'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +contract('balanceDifference', function ([sender, receiver]) { + it('returns balance increments', async function () { + (await balanceDifference(receiver, () => + sendEther(sender, receiver, ether(1))) + ).should.be.bignumber.equal(ether(1)); + }); + + it('returns balance decrements', async function () { + (await balanceDifference(sender, () => + sendEther(sender, receiver, ether(1))) + ).should.be.bignumber.equal(ether(-1)); + }); +}); diff --git a/test/payment/PullPayment.test.js b/test/payment/PullPayment.test.js index 1f4bcc525..13b27ff01 100644 --- a/test/payment/PullPayment.test.js +++ b/test/payment/PullPayment.test.js @@ -1,4 +1,4 @@ -const { ethGetBalance } = require('../helpers/web3'); +const { balanceDifference } = require('../helpers/balanceDifference'); const { ether } = require('../helpers/ether'); const BigNumber = web3.BigNumber; @@ -37,16 +37,13 @@ contract('PullPayment', function ([_, payer, payee1, payee2]) { }); it('can withdraw payment', async function () { - const initialBalance = await ethGetBalance(payee1); + (await balanceDifference(payee1, async () => { + await this.contract.callTransfer(payee1, amount, { from: payer }); + (await this.contract.payments(payee1)).should.be.bignumber.equal(amount); - await this.contract.callTransfer(payee1, amount, { from: payer }); + await this.contract.withdrawPayments(payee1); + })).should.be.bignumber.equal(amount); - (await this.contract.payments(payee1)).should.be.bignumber.equal(amount); - - await this.contract.withdrawPayments(payee1); (await this.contract.payments(payee1)).should.be.bignumber.equal(0); - - const balance = await ethGetBalance(payee1); - Math.abs(balance - initialBalance - amount).should.be.lt(1e16); }); }); diff --git a/test/payment/escrow/Escrow.behavior.js b/test/payment/escrow/Escrow.behavior.js index d7a7975e7..7dd0918a4 100644 --- a/test/payment/escrow/Escrow.behavior.js +++ b/test/payment/escrow/Escrow.behavior.js @@ -1,6 +1,7 @@ const expectEvent = require('../../helpers/expectEvent'); const shouldFail = require('../../helpers/shouldFail'); const { ethGetBalance } = require('../../helpers/web3'); +const { balanceDifference } = require('../../helpers/balanceDifference'); const { ether } = require('../../helpers/ether'); const BigNumber = web3.BigNumber; @@ -61,17 +62,13 @@ function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { describe('withdrawals', async function () { it('can withdraw payments', async function () { - const payeeInitialBalance = await ethGetBalance(payee1); - - await this.escrow.deposit(payee1, { from: primary, value: amount }); - await this.escrow.withdraw(payee1, { from: primary }); + (await balanceDifference(payee1, async () => { + await this.escrow.deposit(payee1, { from: primary, value: amount }); + await this.escrow.withdraw(payee1, { from: primary }); + })).should.be.bignumber.equal(amount); (await ethGetBalance(this.escrow.address)).should.be.bignumber.equal(0); - (await this.escrow.depositsOf(payee1)).should.be.bignumber.equal(0); - - const payeeFinalBalance = await ethGetBalance(payee1); - payeeFinalBalance.sub(payeeInitialBalance).should.be.bignumber.equal(amount); }); it('can do an empty withdrawal', async function () { diff --git a/test/payment/escrow/RefundEscrow.test.js b/test/payment/escrow/RefundEscrow.test.js index 1f92e23af..bb5189ddc 100644 --- a/test/payment/escrow/RefundEscrow.test.js +++ b/test/payment/escrow/RefundEscrow.test.js @@ -1,6 +1,6 @@ const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); -const { ethGetBalance } = require('../../helpers/web3'); +const { balanceDifference } = require('../../helpers/balanceDifference'); const { ether } = require('../../helpers/ether'); const { ZERO_ADDRESS } = require('../../helpers/constants'); @@ -73,11 +73,9 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee }); it('allows beneficiary withdrawal', async function () { - const beneficiaryInitialBalance = await ethGetBalance(beneficiary); - await this.escrow.beneficiaryWithdraw(); - const beneficiaryFinalBalance = await ethGetBalance(beneficiary); - - beneficiaryFinalBalance.sub(beneficiaryInitialBalance).should.be.bignumber.equal(amount * refundees.length); + (await balanceDifference(beneficiary, () => + this.escrow.beneficiaryWithdraw() + )).should.be.bignumber.equal(amount * refundees.length); }); it('prevents entering the refund state', async function () { @@ -109,11 +107,9 @@ contract('RefundEscrow', function ([_, primary, beneficiary, refundee1, refundee it('refunds refundees', async function () { for (const refundee of [refundee1, refundee2]) { - const refundeeInitialBalance = await ethGetBalance(refundee); - await this.escrow.withdraw(refundee, { from: primary }); - const refundeeFinalBalance = await ethGetBalance(refundee); - - refundeeFinalBalance.sub(refundeeInitialBalance).should.be.bignumber.equal(amount); + (await balanceDifference(refundee, () => + this.escrow.withdraw(refundee, { from: primary })) + ).should.be.bignumber.equal(amount); } }); From 21ed6bee256a3ce5057d8233f5649b9ab16dc7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 26 Nov 2018 17:41:38 -0300 Subject: [PATCH 164/205] Travis migration (#1517) * Rolled back Travis stages * Rolled back the rolled-back changes. * Renamed jobs, coverage can no longer fail. * Cleaned up the yaml file a bit. * Updated coveralls badge. --- .travis.yml | 23 ++++++++++------------- README.md | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19994b1f6..fc6fc14cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,29 +15,26 @@ jobs: # --elopio - 20180531 fast_finish: true allow_failures: - - env: SOLIDITY_COVERAGE=true - env: SOLC_NIGHTLY=true include: - # Run the unit test suite three times in parallel. - # The first one gets results faster and is the only one required to pass. - # The second one generates the coverage report. - # The third one is to keep us informed about possible issues with the - # upcoming solidity release. - stage: tests - name: "unit tests" + name: "Linter" + script: npm run lint + + - stage: tests + name: "Unit tests" script: npm run test + - stage: tests - name: "unit tests with coverage" + name: "Unit tests with coverage report" script: npm run test env: SOLIDITY_COVERAGE=true + - stage: tests - name: "unit tests with solc nightly" + name: "Unit tests using solc nightly" script: npm run test env: SOLC_NIGHTLY=true - # solidity and javascript style tests. - - stage: tests - name: "static tests" - script: npm run lint + - stage: update docs if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ addons: diff --git a/README.md b/README.md index 0b309d7c8..b6f9ed67d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # OpenZeppelin [![NPM Package](https://img.shields.io/npm/v/openzeppelin-solidity.svg?style=flat-square)](https://www.npmjs.org/package/openzeppelin-solidity) -[![Build Status](https://img.shields.io/travis/OpenZeppelin/openzeppelin-solidity.svg?branch=master&style=flat-square)](https://travis-ci.org/OpenZeppelin/openzeppelin-solidity) -[![Coverage Status](https://img.shields.io/coveralls/github/OpenZeppelin/openzeppelin-solidity/master.svg?style=flat-square)](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master) +[![Build Status](https://travis-ci.com/OpenZeppelin/openzeppelin-solidity.svg?branch=master)](https://travis-ci.com/OpenZeppelin/openzeppelin-solidity) +[![Coverage Status](https://coveralls.io/repos/github/OpenZeppelin/openzeppelin-solidity/badge.svg?branch=master)](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master) **OpenZeppelin is a library for secure smart contract development.** It provides implementations of standards like ERC20 and ERC721 which you can deploy as-is or extend to suit your needs, as well as Solidity components to build custom contracts and more complex decentralized systems. From f0e12d5301e0cfb862ee3d60b1bf3041230c741d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 27 Nov 2018 17:20:21 -0300 Subject: [PATCH 165/205] ether and shouldFail tests (#1513) * Added ether tests. * Added shouldFail base function and tests. * Updated test descriptions. * Reduced gas limit on out-of-gas tests. --- contracts/mocks/Failer.sol | 22 +++++++ test/helpers/shouldFail.js | 20 ++++-- test/helpers/test/ether.test.js | 16 +++++ test/helpers/test/shouldFail.test.js | 95 ++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 contracts/mocks/Failer.sol create mode 100644 test/helpers/test/ether.test.js create mode 100644 test/helpers/test/shouldFail.test.js diff --git a/contracts/mocks/Failer.sol b/contracts/mocks/Failer.sol new file mode 100644 index 000000000..2b25be41e --- /dev/null +++ b/contracts/mocks/Failer.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.4.24; + +contract Failer { + uint256[] private array; + + function dontFail() public pure { + } + + function failWithRevert() public pure { + revert(); + } + + function failWithThrow() public pure { + assert(false); + } + + function failWithOutOfGas() public { + for (uint256 i = 0; i < 2**200; ++i) { + array.push(i); + } + } +} diff --git a/test/helpers/shouldFail.js b/test/helpers/shouldFail.js index 45e72f921..a64e1a59c 100644 --- a/test/helpers/shouldFail.js +++ b/test/helpers/shouldFail.js @@ -5,11 +5,13 @@ async function shouldFailWithMessage (promise, message) { try { await promise; } catch (error) { - error.message.should.include(message, 'Wrong failure type'); + if (message) { + error.message.should.include(message, `Wrong failure type, expected '${message}'`); + } return; } - should.fail(`Expected '${message}' failure not received`); + should.fail('Expected failure not received'); } async function reverting (promise) { @@ -24,8 +26,12 @@ async function outOfGas (promise) { await shouldFailWithMessage(promise, 'out of gas'); } -module.exports = { - reverting, - throwing, - outOfGas, -}; +async function shouldFail (promise) { + await shouldFailWithMessage(promise); +} + +shouldFail.reverting = reverting; +shouldFail.throwing = throwing; +shouldFail.outOfGas = outOfGas; + +module.exports = shouldFail; diff --git a/test/helpers/test/ether.test.js b/test/helpers/test/ether.test.js new file mode 100644 index 000000000..c06161571 --- /dev/null +++ b/test/helpers/test/ether.test.js @@ -0,0 +1,16 @@ +const { ether } = require('../ether'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('ether', function () { + it('returns a BigNumber', function () { + ether(1, 'ether').should.be.bignumber.equal(new BigNumber(1000000000000000000)); + }); + + it('works with negative amounts', function () { + ether(-1, 'ether').should.be.bignumber.equal(new BigNumber(-1000000000000000000)); + }); +}); diff --git a/test/helpers/test/shouldFail.test.js b/test/helpers/test/shouldFail.test.js new file mode 100644 index 000000000..8f99efe30 --- /dev/null +++ b/test/helpers/test/shouldFail.test.js @@ -0,0 +1,95 @@ +const shouldFail = require('../shouldFail'); + +const BigNumber = web3.BigNumber; +const should = require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +const Failer = artifacts.require('Failer'); + +async function assertFailure (promise) { + try { + await promise; + } catch (error) { + return; + } + should.fail(); +} + +describe('shouldFail', function () { + beforeEach(async function () { + this.failer = await Failer.new(); + }); + + describe('shouldFail', function () { + it('rejects if no failure occurs', async function () { + await assertFailure(shouldFail(this.failer.dontFail())); + }); + + it('accepts a revert', async function () { + await shouldFail(this.failer.failWithRevert()); + }); + + it('accepts a throw', async function () { + await shouldFail(this.failer.failWithThrow()); + }); + + it('accepts an out of gas', async function () { + await shouldFail(this.failer.failWithOutOfGas({ gas: 2000000 })); + }); + }); + + describe('reverting', function () { + it('rejects if no failure occurs', async function () { + await assertFailure(shouldFail.reverting(this.failer.dontFail())); + }); + + it('accepts a revert', async function () { + await shouldFail.reverting(this.failer.failWithRevert()); + }); + + it('rejects a throw', async function () { + await assertFailure(shouldFail.reverting(this.failer.failWithThrow())); + }); + + it('rejects an outOfGas', async function () { + await assertFailure(shouldFail.reverting(this.failer.failWithOutOfGas({ gas: 2000000 }))); + }); + }); + + describe('throwing', function () { + it('rejects if no failure occurs', async function () { + await assertFailure(shouldFail.throwing(this.failer.dontFail())); + }); + + it('accepts a throw', async function () { + await shouldFail.throwing(this.failer.failWithThrow()); + }); + + it('rejects a throw', async function () { + await assertFailure(shouldFail.throwing(this.failer.failWithRevert())); + }); + + it('rejects an outOfGas', async function () { + await assertFailure(shouldFail.throwing(this.failer.failWithOutOfGas({ gas: 2000000 }))); + }); + }); + + describe('outOfGas', function () { + it('rejects if no failure occurs', async function () { + await assertFailure(shouldFail.outOfGas(this.failer.dontFail())); + }); + + it('accepts an out of gas', async function () { + await shouldFail.outOfGas(this.failer.failWithOutOfGas({ gas: 2000000 })); + }); + + it('rejects a revert', async function () { + await assertFailure(shouldFail.outOfGas(this.failer.failWithRevert())); + }); + + it('rejects a throw', async function () { + await assertFailure(shouldFail.outOfGas(this.failer.failWithThrow())); + }); + }); +}); From c2de8ffd146c456bf9a3193732ceb42d6eb2101c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 27 Nov 2018 17:56:26 -0300 Subject: [PATCH 166/205] Now testing events in constructors! (#1511) * Added inTransaction tests. * Added expectEvent.inConstructor. * Changed inTransaction, removed decodeLogs. * Flipped comparison to improve the error message. * Improved expectEvent tests. * Migrated tests to use expectEvent. * Added roles constructor tests. * Fixed linter errors. * Made lodash a dev dependency. * Added more inLogs tests. * Update expectEvent.test.js * Removed lodash. * Moved role constructor tests to public role behavior. * Revert "Flipped comparison to improve the error message." This reverts commit 438c57833d997d2972a7730180a266bc3c6a87c5. * Replaced chai-as-promised with shouldFail. --- contracts/mocks/EventEmitter.sol | 19 +++ package-lock.json | 6 +- package.json | 3 +- test/access/roles/PublicRole.behavior.js | 6 + test/examples/SimpleToken.test.js | 14 +-- test/helpers/decodeLogs.js | 12 -- test/helpers/expectEvent.js | 22 +++- test/helpers/test/expectEvent.test.js | 148 ++++++++++++++++++++++- test/token/ERC721/ERC721.behavior.js | 37 +++--- 9 files changed, 218 insertions(+), 49 deletions(-) delete mode 100644 test/helpers/decodeLogs.js diff --git a/contracts/mocks/EventEmitter.sol b/contracts/mocks/EventEmitter.sol index 257b23651..0a954f37b 100644 --- a/contracts/mocks/EventEmitter.sol +++ b/contracts/mocks/EventEmitter.sol @@ -11,6 +11,12 @@ contract EventEmitter { event String(string value); event LongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue); + constructor (uint8 uintValue, bool booleanValue, string stringValue) public { + emit ShortUint(uintValue); + emit Boolean(booleanValue); + emit String(stringValue); + } + function emitArgumentless() public { emit Argumentless(); } @@ -51,4 +57,17 @@ contract EventEmitter { emit LongUint(uintValue); emit Boolean(boolValue); } + + function emitStringAndEmitIndirectly(string value, IndirectEventEmitter emitter) public { + emit String(value); + emitter.emitStringIndirectly(value); + } +} + +contract IndirectEventEmitter { + event IndirectString(string value); + + function emitStringIndirectly(string value) public { + emit IndirectString(value); + } } diff --git a/package-lock.json b/package-lock.json index 9e2fe893b..0f9afe9b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6885,9 +6885,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.assign": { diff --git a/package.json b/package.json index f97f1050a..58aaec9fe 100644 --- a/package.json +++ b/package.json @@ -55,5 +55,6 @@ "truffle": "^4.1.13", "truffle-hdwallet-provider": "0.0.5", "web3-utils": "^1.0.0-beta.34" - } + }, + "dependencies": {} } diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index 0ae8a19e6..996f843d1 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -19,6 +19,12 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role (await this.contract[`is${rolename}`](anyone)).should.equal(false); }); + it('emits events during construction', async function () { + await expectEvent.inConstruction(this.contract, `${rolename}Added`, { + account: authorized, + }); + }); + it('reverts when querying roles for the null account', async function () { await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS)); }); diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index e7f8fa5c1..091f31715 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -1,4 +1,4 @@ -const { decodeLogs } = require('../helpers/decodeLogs'); +const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); const SimpleToken = artifacts.require('SimpleToken'); @@ -31,12 +31,10 @@ contract('SimpleToken', function ([_, creator]) { creatorBalance.should.be.bignumber.equal(totalSupply); - const receipt = await web3.eth.getTransactionReceipt(this.token.transactionHash); - const logs = decodeLogs(receipt.logs, SimpleToken, this.token.address); - logs.length.should.equal(1); - logs[0].event.should.equal('Transfer'); - logs[0].args.from.valueOf().should.equal(ZERO_ADDRESS); - logs[0].args.to.valueOf().should.equal(creator); - logs[0].args.value.should.be.bignumber.equal(totalSupply); + await expectEvent.inConstruction(this.token, 'Transfer', { + from: ZERO_ADDRESS, + to: creator, + value: totalSupply, + }); }); }); diff --git a/test/helpers/decodeLogs.js b/test/helpers/decodeLogs.js deleted file mode 100644 index 1f1bc946c..000000000 --- a/test/helpers/decodeLogs.js +++ /dev/null @@ -1,12 +0,0 @@ -const SolidityEvent = require('web3/lib/web3/event.js'); - -function decodeLogs (logs, contract, address) { - return logs.map(log => { - const event = new SolidityEvent(null, contract.events[log.topics[0]], address); - return event.decode(log); - }); -} - -module.exports = { - decodeLogs, -}; diff --git a/test/helpers/expectEvent.js b/test/helpers/expectEvent.js index b857b6636..690a09979 100644 --- a/test/helpers/expectEvent.js +++ b/test/helpers/expectEvent.js @@ -1,3 +1,5 @@ +const SolidityEvent = require('web3/lib/web3/event.js'); + const BigNumber = web3.BigNumber; const should = require('chai') .use(require('chai-bignumber')(BigNumber)) @@ -16,8 +18,14 @@ function inLogs (logs, eventName, eventArgs = {}) { return event; } -async function inTransaction (tx, eventName, eventArgs = {}) { - const { logs } = await tx; +async function inConstruction (contract, eventName, eventArgs = {}) { + return inTransaction(contract.transactionHash, contract.constructor, eventName, eventArgs); +} + +async function inTransaction (txHash, emitter, eventName, eventArgs = {}) { + const receipt = await web3.eth.getTransactionReceipt(txHash); + const logs = decodeLogs(receipt.logs, emitter.events); + return inLogs(logs, eventName, eventArgs); } @@ -35,7 +43,17 @@ function isBigNumber (object) { (object.constructor && object.constructor.name === 'BigNumber'); } +function decodeLogs (logs, events) { + return Array.prototype.concat(...logs.map(log => + log.topics.filter(topic => topic in events).map(topic => { + const event = new SolidityEvent(null, events[topic], 0); + return event.decode(log); + }) + )); +} + module.exports = { inLogs, + inConstruction, inTransaction, }; diff --git a/test/helpers/test/expectEvent.test.js b/test/helpers/test/expectEvent.test.js index 158a9f374..c5d09a4ed 100644 --- a/test/helpers/test/expectEvent.test.js +++ b/test/helpers/test/expectEvent.test.js @@ -1,5 +1,8 @@ const expectEvent = require('../expectEvent'); +const shouldFail = require('../shouldFail'); + const EventEmitter = artifacts.require('EventEmitter'); +const IndirectEventEmitter = artifacts.require('IndirectEventEmitter'); const BigNumber = web3.BigNumber; const should = require('chai') @@ -8,7 +11,57 @@ const should = require('chai') describe('expectEvent', function () { beforeEach(async function () { - this.emitter = await EventEmitter.new(); + this.constructionValues = { + uint: 42, + boolean: true, + string: 'OpenZeppelin', + }; + + this.emitter = await EventEmitter.new( + this.constructionValues.uint, + this.constructionValues.boolean, + this.constructionValues.string + ); + }); + + describe('inConstructor', function () { + context('short uint value', function () { + it('accepts emitted events with correct number', async function () { + await expectEvent.inConstruction(this.emitter, 'ShortUint', + { value: this.constructionValues.uint } + ); + }); + + it('throws if an incorrect value is passed', async function () { + await shouldFail(expectEvent.inConstruction(this.emitter, 'ShortUint', { value: 23 })); + }); + }); + + context('boolean value', function () { + it('accepts emitted events with correct value', async function () { + await expectEvent.inConstruction(this.emitter, 'Boolean', { value: this.constructionValues.boolean }); + }); + + it('throws if an incorrect value is passed', async function () { + await shouldFail(expectEvent.inConstruction(this.emitter, 'Boolean', + { value: !this.constructionValues.boolean } + )); + }); + }); + + context('string value', function () { + it('accepts emitted events with correct string', async function () { + await expectEvent.inConstruction(this.emitter, 'String', { value: this.constructionValues.string }); + }); + + it('throws if an incorrect string is passed', async function () { + await shouldFail(expectEvent.inConstruction(this.emitter, 'String', { value: 'ClosedZeppelin' })); + }); + }); + + it('throws if an unemitted event is requested', async function () { + await shouldFail(expectEvent.inConstruction(this.emitter, 'UnemittedEvent')); + }); }); describe('inLogs', function () { @@ -228,5 +281,98 @@ describe('expectEvent', function () { should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false })); }); }); + + describe('with events emitted by an indirectly called contract', function () { + beforeEach(async function () { + this.secondEmitter = await IndirectEventEmitter.new(); + + this.value = 'OpenZeppelin'; + ({ logs: this.logs } = await this.emitter.emitStringAndEmitIndirectly(this.value, this.secondEmitter.address)); + }); + + it('accepts events emitted by the directly called contract', function () { + expectEvent.inLogs(this.logs, 'String', { value: this.value }); + }); + + it('throws when passing events emitted by the indirectly called contract', function () { + should.Throw(() => expectEvent.inLogs(this.logs, 'IndirectString', { value: this.value })); + }); + }); + }); + + describe('inTransaction', function () { + describe('when emitting from called contract and indirect calls', function () { + context('string value', function () { + beforeEach(async function () { + this.secondEmitter = await IndirectEventEmitter.new(); + + this.value = 'OpenZeppelin'; + const receipt = await this.emitter.emitStringAndEmitIndirectly(this.value, this.secondEmitter.address); + this.txHash = receipt.tx; + }); + + context('with directly called contract', function () { + it('accepts emitted events with correct string', async function () { + await expectEvent.inTransaction(this.txHash, EventEmitter, 'String', { value: this.value }); + }); + + it('throws if an unemitted event is requested', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'UnemittedEvent', + { value: this.value } + )); + }); + + it('throws if an incorrect string is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'String', + { value: 'ClosedZeppelin' } + )); + }); + + it('throws if an event emitted from other contract is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', + { value: this.value } + )); + }); + + it('throws if an incorrect emitter is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', + { value: this.value } + )); + }); + }); + + context('with indirectly called contract', function () { + it('accepts events emitted from other contracts', async function () { + await expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString', + { value: this.value } + ); + }); + + it('throws if an unemitted event is requested', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'UnemittedEvent', + { value: this.value } + )); + }); + + it('throws if an incorrect string is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString', + { value: 'ClosedZeppelin' } + )); + }); + + it('throws if an event emitted from other contract is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String', + { value: this.value } + )); + }); + + it('throws if an incorrect emitter is passed', async function () { + await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString', + { value: this.value } + )); + }); + }); + }); + }); }); }); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index aea385a99..de58710bf 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -2,7 +2,6 @@ const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const { decodeLogs } = require('../../helpers/decodeLogs'); const { sendTransaction } = require('../../helpers/sendTransaction'); const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol'); @@ -245,31 +244,25 @@ function shouldBehaveLikeERC721 ( shouldTransferTokensByUsers(transferFun); it('should call onERC721Received', async function () { - const result = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner }); - result.receipt.logs.length.should.be.equal(2); - const [log] = decodeLogs([result.receipt.logs[1]], ERC721ReceiverMock, this.receiver.address); - log.event.should.be.equal('Received'); - log.args.operator.should.be.equal(owner); - log.args.from.should.be.equal(owner); - log.args.tokenId.toNumber().should.be.equal(tokenId); - log.args.data.should.be.equal(data); + const receipt = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner }); + + await expectEvent.inTransaction(receipt.tx, ERC721ReceiverMock, 'Received', { + operator: owner, + from: owner, + tokenId: tokenId, + data: data, + }); }); it('should call onERC721Received from approved', async function () { - const result = await transferFun.call(this, owner, this.receiver.address, tokenId, { - from: approved, + const receipt = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: approved }); + + await expectEvent.inTransaction(receipt.tx, ERC721ReceiverMock, 'Received', { + operator: approved, + from: owner, + tokenId: tokenId, + data: data, }); - result.receipt.logs.length.should.be.equal(2); - const [log] = decodeLogs( - [result.receipt.logs[1]], - ERC721ReceiverMock, - this.receiver.address - ); - log.event.should.be.equal('Received'); - log.args.operator.should.be.equal(approved); - log.args.from.should.be.equal(owner); - log.args.tokenId.toNumber().should.be.equal(tokenId); - log.args.data.should.be.equal(data); }); describe('with an invalid token id', function () { From 6407d7818d3d101ca834b126dbd8f902e5b06c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 27 Nov 2018 19:21:08 -0300 Subject: [PATCH 167/205] Added time helper tests. (#1521) * Added time tests. * Minor improvements. --- test/helpers/test/time.test.js | 68 ++++++++++++++++++++++++++++++++++ test/helpers/time.js | 4 +- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/helpers/test/time.test.js diff --git a/test/helpers/test/time.test.js b/test/helpers/test/time.test.js new file mode 100644 index 000000000..22199906c --- /dev/null +++ b/test/helpers/test/time.test.js @@ -0,0 +1,68 @@ +const time = require('../time'); +const shouldFail = require('../shouldFail'); +const { advanceBlock } = require('../advanceToBlock'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +describe('time', function () { + const TOLERANCE_SECONDS = 1; + + beforeEach(async function () { + await advanceBlock(); + this.start = await time.latest(); + }); + + describe('increase', function () { + it('increases time by a duration', async function () { + await time.increase(time.duration.hours(1)); + + const end = this.start + time.duration.hours(1); + (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); + }); + + it('throws with negative durations', async function () { + await shouldFail(time.increase(-1)); + }); + }); + + describe('increaseTo', function () { + it('increases time to a time in the future', async function () { + const end = this.start + time.duration.hours(1); + await time.increaseTo(end); + (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); + }); + + it('throws with a time in the past', async function () { + await shouldFail(time.increaseTo(this.start - 30)); + }); + }); + + describe('duration', function () { + it('converts seconds to seconds', function () { + time.duration.seconds(1).should.equal(1); + }); + + it('converts minutes to seconds', function () { + time.duration.minutes(1).should.equal(60); + }); + + it('converts hours to seconds', function () { + time.duration.hours(1).should.equal(60 * 60); + }); + + it('converts days to seconds', function () { + time.duration.days(1).should.equal(60 * 60 * 24); + }); + + it('converts weeks to seconds', function () { + time.duration.weeks(1).should.equal(60 * 60 * 24 * 7); + }); + + it('converts years to seconds', function () { + time.duration.years(1).should.equal(60 * 60 * 24 * 365); + }); + }); +}); diff --git a/test/helpers/time.js b/test/helpers/time.js index b7f3c0001..26109db30 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -11,6 +11,8 @@ function increase (duration) { const id = Date.now(); return new Promise((resolve, reject) => { + if (duration < 0) throw Error(`Cannot increase time by a negative amount (${duration})`); + web3.currentProvider.sendAsync({ jsonrpc: '2.0', method: 'evm_increaseTime', @@ -40,7 +42,7 @@ function increase (duration) { async function increaseTo (target) { const now = (await latest()); - if (target < now) throw Error(`Cannot increase current time(${now}) to a moment in the past(${target})`); + if (target < now) throw Error(`Cannot increase current time (${now}) to a moment in the past (${target})`); const diff = target - now; return increase(diff); } From 7ef273050697178b74dd4530d4b0eb4e5127a8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 29 Nov 2018 12:06:47 -0300 Subject: [PATCH 168/205] Approval events on transferFrom and burnFrom (#1524) * transferFrom now emits an Approval event, indicating the updated allowance. * Updated burnFrom to also emit Approval. * Added notices about the extra Approval events. --- contracts/token/ERC20/ERC20.sol | 15 ++++++++++++--- test/token/ERC20/ERC20.test.js | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index abb43b74d..b41f64462 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -9,6 +9,10 @@ import "../../math/SafeMath.sol"; * @dev Implementation of the basic standard token. * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + * + * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for + * all accounts just by listening to said events. Note that this isn't required by the specification, and other + * compliant implementations may not do it. */ contract ERC20 is IERC20 { using SafeMath for uint256; @@ -73,7 +77,9 @@ contract ERC20 is IERC20 { } /** - * @dev Transfer tokens from one address to another + * @dev Transfer tokens from one address to another. + * Note that while this function emits an Approval event, this is not required as per the specification, + * and other compliant implementations may not emit the event. * @param from address The address which you want to send tokens from * @param to address The address which you want to transfer to * @param value uint256 the amount of tokens to be transferred @@ -81,6 +87,7 @@ contract ERC20 is IERC20 { function transferFrom(address from, address to, uint256 value) public returns (bool) { _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); _transfer(from, to, value); + emit Approval(from, msg.sender, _allowed[from][msg.sender]); return true; } @@ -90,6 +97,7 @@ contract ERC20 is IERC20 { * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol + * Emits an Approval event. * @param spender The address which will spend the funds. * @param addedValue The amount of tokens to increase the allowance by. */ @@ -107,6 +115,7 @@ contract ERC20 is IERC20 { * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol + * Emits an Approval event. * @param spender The address which will spend the funds. * @param subtractedValue The amount of tokens to decrease the allowance by. */ @@ -165,13 +174,13 @@ contract ERC20 is IERC20 { * @dev Internal function that burns an amount of the token of a given * account, deducting from the sender's allowance for said account. Uses the * internal burn function. + * Emits an Approval event (reflecting the reduced allowance). * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { - // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, - // this function needs to emit an event with the updated approval. _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value); _burn(account, value); + emit Approval(account, msg.sender, _allowed[account][msg.sender]); } } diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index d60e9130c..42bd872fd 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -199,6 +199,16 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { value: amount, }); }); + + it('emits an approval event', async function () { + const { logs } = await this.token.transferFrom(owner, to, amount, { from: spender }); + + expectEvent.inLogs(logs, 'Approval', { + owner: owner, + spender: spender, + value: await this.token.allowance(owner, spender), + }); + }); }); describe('when the owner does not have enough balance', function () { @@ -521,7 +531,7 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { (await this.token.allowance(owner, spender)).should.be.bignumber.equal(expectedAllowance); }); - it('emits Transfer event', async function () { + it('emits a Transfer event', async function () { const event = expectEvent.inLogs(this.logs, 'Transfer', { from: owner, to: ZERO_ADDRESS, @@ -529,6 +539,14 @@ contract('ERC20', function ([_, owner, recipient, anotherAccount]) { event.args.value.should.be.bignumber.equal(amount); }); + + it('emits an Approval event', async function () { + expectEvent.inLogs(this.logs, 'Approval', { + owner: owner, + spender: spender, + value: await this.token.allowance(owner, spender), + }); + }); }); }; From 6fd0010325740926487788bb5b711f28b242decf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 29 Nov 2018 18:23:20 -0300 Subject: [PATCH 169/205] Moved advanceBlock to time. (#1523) * Added advanceBlock to time, moved tests around. * Removed the standalone advanceBlock. * Removed the 'id' field * Fixed linter error. * Removed the 'latest' test, since it only works if time hasn't been fast-forwarded. * Removed .only directive. --- test/crowdsale/FinalizableCrowdsale.test.js | 3 +- .../IncreasingPriceCrowdsale.test.js | 3 +- test/crowdsale/PostDeliveryCrowdsale.test.js | 3 +- test/crowdsale/RefundableCrowdsale.test.js | 3 +- test/crowdsale/TimedCrowdsale.test.js | 3 +- test/examples/SampleCrowdsale.test.js | 3 +- test/helpers/advanceToBlock.js | 15 ---- test/helpers/test/advanceToBlock.test.js | 19 ----- test/helpers/test/time.test.js | 71 +++++++++++-------- test/helpers/time.js | 38 +++++----- 10 files changed, 63 insertions(+), 98 deletions(-) delete mode 100644 test/helpers/advanceToBlock.js delete mode 100644 test/helpers/test/advanceToBlock.test.js diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 93d406432..48b71d51d 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -1,5 +1,4 @@ const expectEvent = require('../helpers/expectEvent'); -const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); @@ -17,7 +16,7 @@ contract('FinalizableCrowdsale', function ([_, wallet, anyone]) { before(async function () { // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache - await advanceBlock(); + await time.advanceBlock(); }); beforeEach(async function () { diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 41906d224..34b476186 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -1,5 +1,4 @@ const { ether } = require('../helpers/ether'); -const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); @@ -27,7 +26,7 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) const rateAtTime450000 = new BigNumber(6439); beforeEach(async function () { - await advanceBlock(); + await time.advanceBlock(); this.startTime = (await time.latest()) + time.duration.weeks(1); this.closingTime = this.startTime + time.duration.weeks(1); this.afterClosingTime = this.closingTime + time.duration.seconds(1); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 723cb1fca..58d8c1123 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -1,4 +1,3 @@ -const { advanceBlock } = require('../helpers/advanceToBlock'); const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); @@ -18,7 +17,7 @@ contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { before(async function () { // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache - await advanceBlock(); + await time.advanceBlock(); }); beforeEach(async function () { diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 8472b87f2..ce16f66f5 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -1,5 +1,4 @@ const { ether } = require('../helpers/ether'); -const { advanceBlock } = require('../helpers/advanceToBlock'); const { balanceDifference } = require('../helpers/balanceDifference'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); @@ -22,7 +21,7 @@ contract('RefundableCrowdsale', function ([_, wallet, investor, purchaser, anyon before(async function () { // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache - await advanceBlock(); + await time.advanceBlock(); }); beforeEach(async function () { diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index 5b0b457b7..4689ad820 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -1,5 +1,4 @@ const { ether } = require('../helpers/ether'); -const { advanceBlock } = require('../helpers/advanceToBlock'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); @@ -19,7 +18,7 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) { before(async function () { // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache - await advanceBlock(); + await time.advanceBlock(); }); beforeEach(async function () { diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index da0bf1f7c..51df3c40e 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -1,5 +1,4 @@ const { ether } = require('../helpers/ether'); -const { advanceBlock } = require('../helpers/advanceToBlock'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); const { balanceDifference } = require('../helpers/balanceDifference'); @@ -20,7 +19,7 @@ contract('SampleCrowdsale', function ([_, deployer, owner, wallet, investor]) { before(async function () { // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache - await advanceBlock(); + await time.advanceBlock(); }); beforeEach(async function () { diff --git a/test/helpers/advanceToBlock.js b/test/helpers/advanceToBlock.js deleted file mode 100644 index 225502022..000000000 --- a/test/helpers/advanceToBlock.js +++ /dev/null @@ -1,15 +0,0 @@ -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); - }); - }); -} - -module.exports = { - advanceBlock, -}; diff --git a/test/helpers/test/advanceToBlock.test.js b/test/helpers/test/advanceToBlock.test.js deleted file mode 100644 index cd8f1c352..000000000 --- a/test/helpers/test/advanceToBlock.test.js +++ /dev/null @@ -1,19 +0,0 @@ -const advanceToBlock = require('../advanceToBlock'); - -const BigNumber = web3.BigNumber; -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); - -describe('advanceToBlock', function () { - beforeEach(function () { - this.startingBlock = web3.eth.blockNumber; - }); - - describe('advanceBlock', function () { - it('increases the block number by one', async function () { - await advanceToBlock.advanceBlock(); - web3.eth.blockNumber.should.be.bignumber.equal(this.startingBlock + 1); - }); - }); -}); diff --git a/test/helpers/test/time.test.js b/test/helpers/test/time.test.js index 22199906c..556ae92f8 100644 --- a/test/helpers/test/time.test.js +++ b/test/helpers/test/time.test.js @@ -1,6 +1,5 @@ const time = require('../time'); const shouldFail = require('../shouldFail'); -const { advanceBlock } = require('../advanceToBlock'); const BigNumber = web3.BigNumber; require('chai') @@ -10,36 +9,6 @@ require('chai') describe('time', function () { const TOLERANCE_SECONDS = 1; - beforeEach(async function () { - await advanceBlock(); - this.start = await time.latest(); - }); - - describe('increase', function () { - it('increases time by a duration', async function () { - await time.increase(time.duration.hours(1)); - - const end = this.start + time.duration.hours(1); - (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); - }); - - it('throws with negative durations', async function () { - await shouldFail(time.increase(-1)); - }); - }); - - describe('increaseTo', function () { - it('increases time to a time in the future', async function () { - const end = this.start + time.duration.hours(1); - await time.increaseTo(end); - (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); - }); - - it('throws with a time in the past', async function () { - await shouldFail(time.increaseTo(this.start - 30)); - }); - }); - describe('duration', function () { it('converts seconds to seconds', function () { time.duration.seconds(1).should.equal(1); @@ -65,4 +34,44 @@ describe('time', function () { time.duration.years(1).should.equal(60 * 60 * 24 * 365); }); }); + + describe('advanceBlock', function () { + it('increases the block number by one', async function () { + const startingBlock = web3.eth.blockNumber; + await time.advanceBlock(); + web3.eth.blockNumber.should.be.bignumber.equal(startingBlock + 1); + }); + }); + + context('with starting time', function () { + beforeEach(async function () { + await time.advanceBlock(); + this.start = await time.latest(); + }); + + describe('increase', function () { + it('increases time by a duration', async function () { + await time.increase(time.duration.hours(1)); + + const end = this.start + time.duration.hours(1); + (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); + }); + + it('throws with negative durations', async function () { + await shouldFail(time.increase(-1)); + }); + }); + + describe('increaseTo', function () { + it('increases time to a time in the future', async function () { + const end = this.start + time.duration.hours(1); + await time.increaseTo(end); + (await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS); + }); + + it('throws with a time in the past', async function () { + await shouldFail(time.increaseTo(this.start - 30)); + }); + }); + }); }); diff --git a/test/helpers/time.js b/test/helpers/time.js index 26109db30..727250831 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -1,4 +1,12 @@ const { ethGetBlock } = require('./web3'); +const { promisify } = require('util'); + +function advanceBlock () { + return promisify(web3.currentProvider.sendAsync)({ + jsonrpc: '2.0', + method: 'evm_mine', + }); +} // Returns the time of the last mined block in seconds async function latest () { @@ -7,29 +15,16 @@ async function latest () { } // Increases ganache time by the passed duration in seconds -function increase (duration) { - const id = Date.now(); +async function increase (duration) { + if (duration < 0) throw Error(`Cannot increase time by a negative amount (${duration})`); - return new Promise((resolve, reject) => { - if (duration < 0) throw Error(`Cannot increase time by a negative amount (${duration})`); - - web3.currentProvider.sendAsync({ - jsonrpc: '2.0', - method: 'evm_increaseTime', - params: [duration], - 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); - }); - }); + await promisify(web3.currentProvider.sendAsync)({ + jsonrpc: '2.0', + method: 'evm_increaseTime', + params: [duration], }); + + await advanceBlock(); } /** @@ -57,6 +52,7 @@ const duration = { }; module.exports = { + advanceBlock, latest, increase, increaseTo, From 8dae261d2015138243e7cf7d18e63d7b602a27d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 29 Nov 2018 19:09:36 -0300 Subject: [PATCH 170/205] Deleted transactionMined (unused). (#1527) --- test/helpers/transactionMined.js | 34 -------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 test/helpers/transactionMined.js diff --git a/test/helpers/transactionMined.js b/test/helpers/transactionMined.js deleted file mode 100644 index 77401ead6..000000000 --- a/test/helpers/transactionMined.js +++ /dev/null @@ -1,34 +0,0 @@ -// From https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6 -function transactionMined (txnHash, interval) { - interval = interval || 500; - const transactionReceiptAsync = function (txnHash, resolve, reject) { - try { - const 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)) { - return Promise.all(txnHash.map(hash => - web3.eth.getTransactionReceiptMined(hash, interval) - )); - } else { - return new Promise(function (resolve, reject) { - transactionReceiptAsync(txnHash, resolve, reject); - }); - } -} - -web3.eth.transactionMined = transactionMined; - -module.exports = { - transactionMined, -}; From 714ab21a6e582c9c6915f4f5f7debc35dea6edd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 29 Nov 2018 19:10:43 -0300 Subject: [PATCH 171/205] Added mocha-no-only ESlint plugin. (#1529) --- .eslintrc | 11 +++++++---- package-lock.json | 15 +++++++++++++++ package.json | 1 + 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.eslintrc b/.eslintrc index c15a4d515..c06f6e872 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,22 +1,23 @@ { "extends" : [ "standard", - "plugin:promise/recommended" + "plugin:promise/recommended", ], "plugins": [ - "promise" + "mocha-no-only", + "promise", ], "env": { "browser" : true, "node" : true, "mocha" : true, - "jest" : true + "jest" : true, }, "globals" : { "artifacts": false, "contract": false, "assert": false, - "web3": false + "web3": false, }, "rules": { @@ -49,6 +50,8 @@ "semi": ["error", "always"], "space-before-function-paren": ["error", "always"], + "mocha-no-only/mocha-no-only": ["error"], + "promise/always-return": "off", "promise/avoid-new": "off", } diff --git a/package-lock.json b/package-lock.json index 0f9afe9b5..2939ecd08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3236,6 +3236,15 @@ } } }, + "eslint-plugin-mocha-no-only": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha-no-only/-/eslint-plugin-mocha-no-only-1.0.0.tgz", + "integrity": "sha512-mCl1QMqzCvZL6JpOYD2eaCiOjuPBJppKUEs7w1JKMfG6cHpzsK/TzNQJmVUR29AK+cYIWDDOJHC78QlHkRMtOQ==", + "dev": true, + "requires": { + "requireindex": "~1.1.0" + } + }, "eslint-plugin-node": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", @@ -8520,6 +8529,12 @@ "resolve-from": "^1.0.0" } }, + "requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=", + "dev": true + }, "resolve": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", diff --git a/package.json b/package.json index 58aaec9fe..34c188877 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "eslint": "^4.19.1", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.13.0", + "eslint-plugin-mocha-no-only": "^1.0.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.8.0", "eslint-plugin-standard": "^3.1.0", From 9faebb5365f60378f90747b66bd523eda7516e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 29 Nov 2018 23:10:03 -0300 Subject: [PATCH 172/205] Added makeInterfaceId tests. (#1530) --- contracts/mocks/OwnableInterfaceId.sol | 15 +++++++++++++++ test/helpers/test/makeInterfaceId.test.js | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 contracts/mocks/OwnableInterfaceId.sol create mode 100644 test/helpers/test/makeInterfaceId.test.js diff --git a/contracts/mocks/OwnableInterfaceId.sol b/contracts/mocks/OwnableInterfaceId.sol new file mode 100644 index 000000000..14c943d50 --- /dev/null +++ b/contracts/mocks/OwnableInterfaceId.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.24; + +import "../ownership/Ownable.sol"; + +/** + * @title Ownable interface id calculator. + * @dev See the EIP165 specification for more information: + * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md#specification + */ +contract OwnableInterfaceId { + function getInterfaceId() public pure returns (bytes4) { + Ownable i; + return i.owner.selector ^ i.isOwner.selector ^ i.renounceOwnership.selector ^ i.transferOwnership.selector; + } +} diff --git a/test/helpers/test/makeInterfaceId.test.js b/test/helpers/test/makeInterfaceId.test.js new file mode 100644 index 000000000..fd4920438 --- /dev/null +++ b/test/helpers/test/makeInterfaceId.test.js @@ -0,0 +1,20 @@ +const { makeInterfaceId } = require('../makeInterfaceId'); + +const OwnableInterfaceId = artifacts.require('OwnableInterfaceId'); + +require('chai') + .should(); + +describe('makeInterfaceId', function () { + it('calculates the EIP165 interface id from function signatures', async function () { + const calculator = await OwnableInterfaceId.new(); + const ownableId = await calculator.getInterfaceId(); + + makeInterfaceId([ + 'owner()', + 'isOwner()', + 'renounceOwnership()', + 'transferOwnership(address)', + ]).should.equal(ownableId); + }); +}); From 88e8c7c94b445c17dd08e5d50f28e9fd67ee0671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Sat, 1 Dec 2018 01:43:25 -0300 Subject: [PATCH 173/205] Updated eslint-mocha-no-only. (#1533) --- package-lock.json | 4047 ++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 2023 insertions(+), 2026 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2939ecd08..53af56d9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" } }, "@nodelib/fs.stat": { @@ -26,7 +26,7 @@ "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", "dev": true, "requires": { - "any-observable": "^0.3.0" + "any-observable": "0.3.0" }, "dependencies": { "any-observable": { @@ -55,7 +55,7 @@ "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", "dev": true, "requires": { - "xtend": "~4.0.0" + "xtend": "4.0.1" } }, "accepts": { @@ -64,7 +64,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "~2.1.18", + "mime-types": "2.1.18", "negotiator": "0.6.1" }, "dependencies": { @@ -80,7 +80,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "1.33.0" } } } @@ -97,7 +97,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "^3.0.4" + "acorn": "3.3.0" }, "dependencies": { "acorn": { @@ -120,10 +120,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { @@ -138,9 +138,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" } }, "amdefine": { @@ -173,8 +173,8 @@ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "2.3.11", + "normalize-path": "2.1.1" } }, "aproba": { @@ -189,8 +189,8 @@ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.3" } }, "argparse": { @@ -199,7 +199,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "arr-diff": { @@ -208,7 +208,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "arr-flatten": { @@ -241,7 +241,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "array-uniq": "1.0.3" } }, "array-uniq": { @@ -304,7 +304,7 @@ "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", "dev": true, "requires": { - "async": "^2.4.0" + "async": "2.6.1" }, "dependencies": { "async": { @@ -313,7 +313,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } } } @@ -354,9 +354,9 @@ "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", "dev": true, "requires": { - "chalk": "^1.1.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" } }, "babel-core": { @@ -365,25 +365,25 @@ "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" }, "dependencies": { "babel-code-frame": { @@ -392,9 +392,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" } }, "babel-runtime": { @@ -403,8 +403,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-template": { @@ -413,11 +413,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.11" } }, "babel-traverse": { @@ -426,15 +426,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.11" } }, "babel-types": { @@ -443,10 +443,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "babylon": { @@ -484,14 +484,14 @@ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.11", + "source-map": "0.5.7", + "trim-right": "1.0.1" }, "dependencies": { "babel-runtime": { @@ -500,8 +500,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -510,10 +510,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "jsesc": { @@ -536,9 +536,9 @@ "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-builder-binary-assignment-operator-visitor": { @@ -547,9 +547,9 @@ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "dev": true, "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-helper-call-delegate": { @@ -558,10 +558,10 @@ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "dev": true, "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.25.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-define-map": { @@ -570,10 +570,10 @@ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" }, "dependencies": { "babel-runtime": { @@ -582,8 +582,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -592,10 +592,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "regenerator-runtime": { @@ -612,9 +612,9 @@ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-explode-class": { @@ -623,10 +623,10 @@ "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", "dev": true, "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.25.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-function-name": { @@ -635,11 +635,11 @@ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-get-function-arity": { @@ -648,8 +648,8 @@ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-helper-hoist-variables": { @@ -658,8 +658,8 @@ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-helper-optimise-call-expression": { @@ -668,8 +668,8 @@ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-helper-regex": { @@ -678,9 +678,9 @@ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" }, "dependencies": { "babel-runtime": { @@ -689,8 +689,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -699,10 +699,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "regenerator-runtime": { @@ -719,11 +719,11 @@ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helper-replace-supers": { @@ -732,12 +732,12 @@ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-helpers": { @@ -746,8 +746,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-messages": { @@ -756,7 +756,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-check-es2015-constants": { @@ -765,7 +765,7 @@ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-syntax-async-functions": { @@ -840,9 +840,9 @@ "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-async-to-generator": { @@ -851,9 +851,9 @@ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-class-constructor-call": { @@ -862,9 +862,9 @@ "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", "dev": true, "requires": { - "babel-plugin-syntax-class-constructor-call": "^6.18.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-class-properties": { @@ -873,10 +873,10 @@ "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-decorators": { @@ -885,11 +885,11 @@ "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", "dev": true, "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-arrow-functions": { @@ -898,7 +898,7 @@ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-block-scoped-functions": { @@ -907,7 +907,7 @@ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-block-scoping": { @@ -916,11 +916,11 @@ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.11" }, "dependencies": { "babel-runtime": { @@ -929,8 +929,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -939,10 +939,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "regenerator-runtime": { @@ -959,15 +959,15 @@ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", "dev": true, "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-computed-properties": { @@ -976,8 +976,8 @@ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-es2015-destructuring": { @@ -986,7 +986,7 @@ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-duplicate-keys": { @@ -995,8 +995,8 @@ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-for-of": { @@ -1005,7 +1005,7 @@ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-function-name": { @@ -1014,9 +1014,9 @@ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-literals": { @@ -1025,7 +1025,7 @@ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-modules-amd": { @@ -1034,9 +1034,9 @@ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-es2015-modules-commonjs": { @@ -1045,10 +1045,10 @@ "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" }, "dependencies": { "babel-runtime": { @@ -1057,8 +1057,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -1067,10 +1067,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "regenerator-runtime": { @@ -1087,9 +1087,9 @@ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "dev": true, "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-es2015-modules-umd": { @@ -1098,9 +1098,9 @@ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0" } }, "babel-plugin-transform-es2015-object-super": { @@ -1109,8 +1109,8 @@ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "dev": true, "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-parameters": { @@ -1119,12 +1119,12 @@ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", "dev": true, "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.25.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-shorthand-properties": { @@ -1133,8 +1133,8 @@ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-spread": { @@ -1143,7 +1143,7 @@ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-sticky-regex": { @@ -1152,9 +1152,9 @@ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "dev": true, "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-plugin-transform-es2015-template-literals": { @@ -1163,7 +1163,7 @@ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-typeof-symbol": { @@ -1172,7 +1172,7 @@ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-es2015-unicode-regex": { @@ -1181,9 +1181,9 @@ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.25.0", + "regexpu-core": "2.0.0" } }, "babel-plugin-transform-exponentiation-operator": { @@ -1192,9 +1192,9 @@ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", "dev": true, "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-export-extensions": { @@ -1203,8 +1203,8 @@ "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", "dev": true, "requires": { - "babel-plugin-syntax-export-extensions": "^6.8.0", - "babel-runtime": "^6.22.0" + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-flow-strip-types": { @@ -1213,8 +1213,8 @@ "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "dev": true, "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-object-rest-spread": { @@ -1223,8 +1223,8 @@ "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.22.0" + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.25.0" } }, "babel-plugin-transform-regenerator": { @@ -1242,8 +1242,8 @@ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0" } }, "babel-preset-env": { @@ -1252,36 +1252,36 @@ "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.24.1", + "browserslist": "3.2.8", + "invariant": "2.2.2", + "semver": "5.4.1" } }, "babel-preset-es2015": { @@ -1290,30 +1290,30 @@ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.22.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-for-of": "^6.22.0", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-umd": "^6.24.1", - "babel-plugin-transform-es2015-object-super": "^6.24.1", - "babel-plugin-transform-es2015-parameters": "^6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", - "babel-plugin-transform-regenerator": "^6.24.1" + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.24.1" } }, "babel-preset-stage-1": { @@ -1322,9 +1322,9 @@ "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", "dev": true, "requires": { - "babel-plugin-transform-class-constructor-call": "^6.24.1", - "babel-plugin-transform-export-extensions": "^6.22.0", - "babel-preset-stage-2": "^6.24.1" + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" } }, "babel-preset-stage-2": { @@ -1333,10 +1333,10 @@ "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", "dev": true, "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" } }, "babel-preset-stage-3": { @@ -1345,11 +1345,11 @@ "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", "dev": true, "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.23.0" } }, "babel-register": { @@ -1358,13 +1358,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.0", + "home-or-tmp": "2.0.0", + "lodash": "4.17.11", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" }, "dependencies": { "babel-runtime": { @@ -1373,8 +1373,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "regenerator-runtime": { @@ -1391,8 +1391,8 @@ "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.10.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.10.5" } }, "babel-template": { @@ -1401,11 +1401,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.11" }, "dependencies": { "babel-runtime": { @@ -1414,8 +1414,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -1424,10 +1424,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "babylon": { @@ -1450,15 +1450,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.11" }, "dependencies": { "babel-code-frame": { @@ -1467,9 +1467,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" } }, "babel-runtime": { @@ -1478,8 +1478,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "core-js": "2.5.0", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -1488,10 +1488,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "babylon": { @@ -1514,10 +1514,10 @@ "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^1.0.1" + "babel-runtime": "6.25.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" } }, "babelify": { @@ -1526,8 +1526,8 @@ "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "dev": true, "requires": { - "babel-core": "^6.0.14", - "object-assign": "^4.0.0" + "babel-core": "6.26.3", + "object-assign": "4.1.1" } }, "babylon": { @@ -1542,7 +1542,7 @@ "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", "dev": true, "requires": { - "precond": "0.2" + "precond": "0.2.3" } }, "balanced-match": { @@ -1557,13 +1557,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -1572,7 +1572,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -1581,7 +1581,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -1590,7 +1590,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -1599,9 +1599,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, "isobject": { @@ -1631,7 +1631,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "big.js": { @@ -1642,7 +1642,6 @@ }, "bignumber.js": { "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "from": "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", "dev": true }, "binary-extensions": { @@ -1669,11 +1668,11 @@ "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", "dev": true, "requires": { - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1", - "safe-buffer": "^5.0.1", - "unorm": "^1.3.3" + "create-hash": "1.1.3", + "pbkdf2": "3.0.16", + "randombytes": "2.0.6", + "safe-buffer": "5.1.1", + "unorm": "1.4.1" } }, "bip66": { @@ -1682,7 +1681,7 @@ "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.1" } }, "bl": { @@ -1691,7 +1690,7 @@ "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", "dev": true, "requires": { - "readable-stream": "^2.0.5" + "readable-stream": "2.3.3" } }, "bn.js": { @@ -1707,15 +1706,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", + "depd": "1.1.2", + "http-errors": "1.6.3", "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", - "type-is": "~1.6.16" + "type-is": "1.6.16" }, "dependencies": { "debug": { @@ -1733,7 +1732,7 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "qs": { @@ -1750,7 +1749,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -1760,9 +1759,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "brorand": { @@ -1783,11 +1782,11 @@ "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", "dev": true, "requires": { - "buffer-xor": "^1.0.2", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "inherits": "^2.0.1" + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.0", + "inherits": "2.0.3" } }, "browserify-sha3": { @@ -1796,7 +1795,7 @@ "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", "dev": true, "requires": { - "js-sha3": "^0.3.1" + "js-sha3": "0.3.1" } }, "browserslist": { @@ -1805,8 +1804,8 @@ "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "caniuse-lite": "1.0.30000860", + "electron-to-chromium": "1.3.50" } }, "bs58": { @@ -1815,7 +1814,7 @@ "integrity": "sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4=", "dev": true, "requires": { - "base-x": "^1.1.0" + "base-x": "1.1.0" } }, "bs58check": { @@ -1824,8 +1823,8 @@ "integrity": "sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g=", "dev": true, "requires": { - "bs58": "^3.1.0", - "create-hash": "^1.1.0" + "bs58": "3.1.0", + "create-hash": "1.1.3" } }, "buffer-from": { @@ -1864,15 +1863,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" }, "dependencies": { "isobject": { @@ -1918,7 +1917,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "^0.2.0" + "callsites": "0.2.0" } }, "callsites": { @@ -1952,8 +1951,8 @@ "dev": true, "optional": true, "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "align-text": "0.1.4", + "lazy-cache": "1.0.4" } }, "chai": { @@ -1962,12 +1961,12 @@ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { - "assertion-error": "^1.0.1", - "check-error": "^1.0.1", - "deep-eql": "^3.0.0", - "get-func-name": "^2.0.0", - "pathval": "^1.0.0", - "type-detect": "^4.0.0" + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" } }, "chai-bignumber": { @@ -1982,11 +1981,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "chardet": { @@ -2007,7 +2006,7 @@ "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", "dev": true, "requires": { - "functional-red-black-tree": "^1.0.1" + "functional-red-black-tree": "1.0.1" } }, "chokidar": { @@ -2016,15 +2015,15 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" } }, "chownr": { @@ -2039,8 +2038,8 @@ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "2.0.3", + "safe-buffer": "5.1.1" } }, "circular-json": { @@ -2055,10 +2054,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -2067,7 +2066,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "isobject": { @@ -2084,7 +2083,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "2.0.0" } }, "cli-spinners": { @@ -2117,7 +2116,7 @@ "dev": true, "requires": { "slice-ansi": "0.0.4", - "string-width": "^1.0.1" + "string-width": "1.0.2" }, "dependencies": { "slice-ansi": { @@ -2140,9 +2139,9 @@ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" } }, "clone": { @@ -2163,7 +2162,7 @@ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "1.0.0" } }, "clone-stats": { @@ -2178,9 +2177,9 @@ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" }, "dependencies": { "process-nextick-args": { @@ -2195,13 +2194,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -2210,7 +2209,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -2233,8 +2232,8 @@ "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", "dev": true, "requires": { - "bs58": "^2.0.1", - "create-hash": "^1.1.1" + "bs58": "2.0.1", + "create-hash": "1.1.3" }, "dependencies": { "bs58": { @@ -2251,8 +2250,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -2261,7 +2260,7 @@ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -2282,7 +2281,7 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "commander": { @@ -2315,10 +2314,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" } }, "console-control-strings": { @@ -2387,8 +2386,8 @@ "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", "dev": true, "requires": { - "object-assign": "^4", - "vary": "^1" + "object-assign": "4.1.1", + "vary": "1.1.2" } }, "coveralls": { @@ -2397,11 +2396,11 @@ "integrity": "sha512-FAzXwiDOYLGDWH+zgoIA+8GbWv50hlx+kpEJyvzLKOdnIBv9uWoVl4DhqGgyUHpiRjAlF8KYZSipWXYtllWH6Q==", "dev": true, "requires": { - "js-yaml": "^3.6.1", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.5", - "minimist": "^1.2.0", - "request": "^2.79.0" + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.7", + "minimist": "1.2.0", + "request": "2.87.0" }, "dependencies": { "minimist": { @@ -2418,10 +2417,10 @@ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", "dev": true, "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.8" } }, "create-hmac": { @@ -2430,12 +2429,12 @@ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", "dev": true, "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" } }, "cross-fetch": { @@ -2454,9 +2453,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" }, "dependencies": { "lru-cache": { @@ -2465,8 +2464,8 @@ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } } } @@ -2489,7 +2488,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "date-fns": { @@ -2537,7 +2536,7 @@ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "1.0.0" } }, "deep-eql": { @@ -2546,7 +2545,7 @@ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "^4.0.0" + "type-detect": "4.0.8" } }, "deep-equal": { @@ -2567,7 +2566,7 @@ "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", "dev": true, "requires": { - "abstract-leveldown": "~2.6.0" + "abstract-leveldown": "2.6.3" } }, "define-properties": { @@ -2576,8 +2575,8 @@ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "foreach": "^2.0.5", - "object-keys": "^1.0.8" + "foreach": "2.0.5", + "object-keys": "1.0.12" } }, "define-property": { @@ -2586,8 +2585,8 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -2596,7 +2595,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -2605,7 +2604,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -2614,9 +2613,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, "isobject": { @@ -2645,13 +2644,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.1" } }, "delayed-stream": { @@ -2690,7 +2689,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "diff": { @@ -2705,8 +2704,8 @@ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" + "arrify": "1.0.1", + "path-type": "3.0.0" }, "dependencies": { "path-type": { @@ -2715,7 +2714,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "pify": { @@ -2732,7 +2731,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.2" } }, "dom-walk": { @@ -2753,9 +2752,9 @@ "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" + "browserify-aes": "1.0.6", + "create-hash": "1.1.3", + "create-hmac": "1.1.6" } }, "duplexer3": { @@ -2771,7 +2770,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0" + "jsbn": "0.1.1" } }, "editions": { @@ -2804,13 +2803,13 @@ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" } }, "emojis-list": { @@ -2831,7 +2830,7 @@ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "dev": true, "requires": { - "iconv-lite": "~0.4.13" + "iconv-lite": "0.4.18" } }, "end-of-stream": { @@ -2840,7 +2839,7 @@ "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "enhanced-resolve": { @@ -2849,9 +2848,9 @@ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" } }, "eol": { @@ -2866,7 +2865,7 @@ "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", "dev": true, "requires": { - "prr": "~0.0.0" + "prr": "0.0.0" }, "dependencies": { "prr": { @@ -2883,8 +2882,8 @@ "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", "dev": true, "requires": { - "string-template": "~0.2.1", - "xtend": "~4.0.0" + "string-template": "0.2.1", + "xtend": "4.0.1" } }, "error-ex": { @@ -2893,7 +2892,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "es-abstract": { @@ -2902,11 +2901,11 @@ "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" }, "dependencies": { "function-bind": { @@ -2923,9 +2922,9 @@ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", "dev": true, "requires": { - "is-callable": "^1.1.1", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" } }, "escape-html": { @@ -2946,11 +2945,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" }, "dependencies": { "estraverse": { @@ -2966,7 +2965,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } } } @@ -2977,44 +2976,44 @@ "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", + "ajv": "5.5.2", + "babel-code-frame": "6.22.0", + "chalk": "2.4.1", + "concat-stream": "1.6.2", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.7.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "1.1.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", "table": "4.0.2", - "text-table": "~0.2.0" + "text-table": "0.2.0" }, "dependencies": { "ansi-regex": { @@ -3029,7 +3028,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "chalk": { @@ -3038,9 +3037,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "debug": { @@ -3070,8 +3069,8 @@ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.0" } }, "strip-ansi": { @@ -3080,7 +3079,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -3089,7 +3088,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -3106,8 +3105,8 @@ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" + "debug": "2.6.9", + "resolve": "1.8.1" }, "dependencies": { "debug": { @@ -3125,7 +3124,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } } } @@ -3136,8 +3135,8 @@ "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, "requires": { - "debug": "^2.6.8", - "pkg-dir": "^1.0.0" + "debug": "2.6.9", + "pkg-dir": "1.0.0" } }, "eslint-plugin-import": { @@ -3146,16 +3145,16 @@ "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==", "dev": true, "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", + "contains-path": "0.1.0", + "debug": "2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" + "eslint-import-resolver-node": "0.3.2", + "eslint-module-utils": "2.2.0", + "has": "1.0.1", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.0", + "resolve": "1.8.1" }, "dependencies": { "doctrine": { @@ -3164,8 +3163,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" + "esutils": "2.0.2", + "isarray": "1.0.0" } }, "find-up": { @@ -3174,7 +3173,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "load-json-file": { @@ -3183,10 +3182,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" } }, "path-type": { @@ -3195,7 +3194,7 @@ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "^2.0.0" + "pify": "2.3.0" } }, "read-pkg": { @@ -3204,9 +3203,9 @@ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" } }, "read-pkg-up": { @@ -3215,8 +3214,8 @@ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" + "find-up": "2.1.0", + "read-pkg": "2.0.0" } }, "resolve": { @@ -3225,7 +3224,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } }, "strip-bom": { @@ -3237,12 +3236,12 @@ } }, "eslint-plugin-mocha-no-only": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha-no-only/-/eslint-plugin-mocha-no-only-1.0.0.tgz", - "integrity": "sha512-mCl1QMqzCvZL6JpOYD2eaCiOjuPBJppKUEs7w1JKMfG6cHpzsK/TzNQJmVUR29AK+cYIWDDOJHC78QlHkRMtOQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha-no-only/-/eslint-plugin-mocha-no-only-1.1.0.tgz", + "integrity": "sha512-YdeWE2KpZxsRs72SFfQobvf9G5Cv25sTbely9AEdn7trstDlhcgCyWl6wH/wYf2a0tJ6At5/BOJO/+9C6QYbVQ==", "dev": true, "requires": { - "requireindex": "~1.1.0" + "requireindex": "1.1.0" } }, "eslint-plugin-node": { @@ -3251,9 +3250,9 @@ "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", + "ignore": "3.3.7", + "minimatch": "3.0.4", + "resolve": "1.4.0", "semver": "5.3.0" }, "dependencies": { @@ -3283,8 +3282,8 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "esrecurse": "4.2.1", + "estraverse": "4.2.0" } }, "eslint-visitor-keys": { @@ -3299,8 +3298,8 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "5.7.1", + "acorn-jsx": "3.0.1" } }, "esprima": { @@ -3315,7 +3314,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "4.2.0" } }, "esrecurse": { @@ -3324,7 +3323,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "4.2.0" } }, "estraverse": { @@ -3351,13 +3350,13 @@ "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", "dev": true, "requires": { - "eth-query": "^2.1.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.3", - "ethjs-util": "^0.1.3", - "json-rpc-engine": "^3.6.0", - "pify": "^2.3.0", - "tape": "^4.6.3" + "eth-query": "2.1.2", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "ethjs-util": "0.1.4", + "json-rpc-engine": "3.7.3", + "pify": "2.3.0", + "tape": "4.9.1" } }, "eth-json-rpc-infura": { @@ -3366,11 +3365,11 @@ "integrity": "sha512-IuK5Iowfs6taluA/3Okmu6EfZcFMq6MQuyrUL1PrCoJstuuBr3TvVeSy3keDyxfbrjFB34nCo538I8G+qMtsbw==", "dev": true, "requires": { - "cross-fetch": "^2.1.1", - "eth-json-rpc-middleware": "^1.5.0", - "json-rpc-engine": "^3.4.0", - "json-rpc-error": "^2.0.0", - "tape": "^4.8.0" + "cross-fetch": "2.2.1", + "eth-json-rpc-middleware": "1.6.0", + "json-rpc-engine": "3.7.3", + "json-rpc-error": "2.0.0", + "tape": "4.9.1" } }, "eth-json-rpc-middleware": { @@ -3379,19 +3378,19 @@ "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", "dev": true, "requires": { - "async": "^2.5.0", - "eth-query": "^2.1.2", - "eth-tx-summary": "^3.1.2", - "ethereumjs-block": "^1.6.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.2", - "ethereumjs-vm": "^2.1.0", - "fetch-ponyfill": "^4.0.0", - "json-rpc-engine": "^3.6.0", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "tape": "^4.6.3" + "async": "2.6.1", + "eth-query": "2.1.2", + "eth-tx-summary": "3.2.3", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.5", + "fetch-ponyfill": "4.1.0", + "json-rpc-engine": "3.7.3", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "tape": "4.9.1" }, "dependencies": { "async": { @@ -3400,7 +3399,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } } } @@ -3411,13 +3410,13 @@ "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", "dev": true, "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "keccakjs": "^0.2.1", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" } }, "eth-query": { @@ -3426,8 +3425,8 @@ "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", "dev": true, "requires": { - "json-rpc-random-id": "^1.0.0", - "xtend": "^4.0.1" + "json-rpc-random-id": "1.0.1", + "xtend": "4.0.1" } }, "eth-sig-util": { @@ -3437,16 +3436,15 @@ "dev": true, "requires": { "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "ethereumjs-util": "^5.1.1" + "ethereumjs-util": "5.2.0" }, "dependencies": { "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "from": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", "dev": true, "requires": { - "bn.js": "^4.10.0", - "ethereumjs-util": "^5.0.0" + "bn.js": "4.11.8", + "ethereumjs-util": "5.2.0" } } } @@ -3457,19 +3455,19 @@ "integrity": "sha512-1gZpA5fKarJOVSb5OUlPnhDQuIazqAkI61zlVvf5LdG47nEgw+/qhyZnuj3CUdE/TLTKuRzPLeyXLjaB4qWTRQ==", "dev": true, "requires": { - "async": "^2.1.2", - "bn.js": "^4.11.8", - "clone": "^2.0.0", - "concat-stream": "^1.5.1", - "end-of-stream": "^1.1.0", - "eth-query": "^2.0.2", - "ethereumjs-block": "^1.4.1", - "ethereumjs-tx": "^1.1.1", - "ethereumjs-util": "^5.0.1", + "async": "2.6.1", + "bn.js": "4.11.8", + "clone": "2.1.1", + "concat-stream": "1.6.2", + "end-of-stream": "1.4.0", + "eth-query": "2.1.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", "ethereumjs-vm": "2.3.4", - "through2": "^2.0.3", - "treeify": "^1.0.1", - "web3-provider-engine": "^13.3.2" + "through2": "2.0.3", + "treeify": "1.1.0", + "web3-provider-engine": "13.8.0" }, "dependencies": { "async": { @@ -3478,7 +3476,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "eth-block-tracker": { @@ -3488,21 +3486,20 @@ "dev": true, "requires": { "async-eventemitter": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "eth-query": "^2.1.0", - "ethereumjs-tx": "^1.3.3", - "ethereumjs-util": "^5.1.3", - "ethjs-util": "^0.1.3", - "json-rpc-engine": "^3.6.0", - "pify": "^2.3.0", - "tape": "^4.6.3" + "eth-query": "2.1.2", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "ethjs-util": "0.1.4", + "json-rpc-engine": "3.7.3", + "pify": "2.3.0", + "tape": "4.9.1" }, "dependencies": { "async-eventemitter": { "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "from": "async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", "dev": true, "requires": { - "async": "^2.4.0" + "async": "2.6.1" } } } @@ -3519,17 +3516,17 @@ "integrity": "sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw==", "dev": true, "requires": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", + "async": "2.6.1", + "async-eventemitter": "0.2.4", "ethereum-common": "0.2.0", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~1.7.0", - "ethereumjs-util": "^5.1.3", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.1.2", - "rustbn.js": "~0.1.1", - "safe-buffer": "^5.1.1" + "ethereumjs-account": "2.0.5", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "5.2.0", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "rustbn.js": "0.1.2", + "safe-buffer": "5.1.1" } }, "web3-provider-engine": { @@ -3538,25 +3535,25 @@ "integrity": "sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ==", "dev": true, "requires": { - "async": "^2.5.0", - "clone": "^2.0.0", - "eth-block-tracker": "^2.2.2", - "eth-sig-util": "^1.4.2", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.2.0", - "ethereumjs-util": "^5.1.1", - "ethereumjs-vm": "^2.0.2", - "fetch-ponyfill": "^4.0.0", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "readable-stream": "^2.2.9", - "request": "^2.67.0", - "semaphore": "^1.0.3", - "solc": "^0.4.2", - "tape": "^4.4.0", - "xhr": "^2.2.0", - "xtend": "^4.0.1" + "async": "2.6.1", + "clone": "2.1.1", + "eth-block-tracker": "2.3.1", + "eth-sig-util": "1.4.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.4", + "fetch-ponyfill": "4.1.0", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "readable-stream": "2.3.3", + "request": "2.87.0", + "semaphore": "1.1.0", + "solc": "0.4.24", + "tape": "4.9.1", + "xhr": "2.4.0", + "xtend": "4.0.1" } } } @@ -3573,9 +3570,9 @@ "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", "dev": true, "requires": { - "ethereumjs-util": "^5.0.0", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" + "ethereumjs-util": "5.2.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.1" } }, "ethereumjs-block": { @@ -3584,11 +3581,11 @@ "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", "dev": true, "requires": { - "async": "^2.0.1", + "async": "2.6.1", "ethereum-common": "0.2.0", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.0", - "merkle-patricia-tree": "^2.1.2" + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" }, "dependencies": { "async": { @@ -3597,7 +3594,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "ethereum-common": { @@ -3614,8 +3611,8 @@ "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", "dev": true, "requires": { - "source-map-support": "^0.5.3", - "webpack-cli": "^2.0.9" + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" }, "dependencies": { "source-map": { @@ -3630,8 +3627,8 @@ "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "buffer-from": "1.1.0", + "source-map": "0.6.1" } } } @@ -3642,8 +3639,8 @@ "integrity": "sha512-cPr0BxitCaffq0qQwZRHJgiNCM/3IIJqkYbweeUCyPwV77S+GlQHou2L3afKEFtfiAjfaa82T9LnSmY/pM8iYQ==", "dev": true, "requires": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" } }, "ethereumjs-util": { @@ -3652,13 +3649,13 @@ "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", "dev": true, "requires": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "ethjs-util": "^0.1.3", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "ethjs-util": "0.1.4", + "keccak": "1.3.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.1", + "secp256k1": "3.3.0" } }, "ethereumjs-vm": { @@ -3667,17 +3664,17 @@ "integrity": "sha512-AJ7x44+xqyE5+UO3Nns19WkTdZfyqFZ+sEjIEpvme7Ipbe3iBU1uwCcHEdiu/yY9bdhr3IfSa/NfIKNeXPaRVQ==", "dev": true, "requires": { - "async": "^2.1.2", - "async-eventemitter": "^0.2.2", + "async": "2.6.1", + "async-eventemitter": "0.2.4", "ethereum-common": "0.2.0", - "ethereumjs-account": "^2.0.3", - "ethereumjs-block": "~1.7.0", - "ethereumjs-util": "^5.1.3", - "fake-merkle-patricia-tree": "^1.0.1", - "functional-red-black-tree": "^1.0.1", - "merkle-patricia-tree": "^2.1.2", - "rustbn.js": "~0.1.1", - "safe-buffer": "^5.1.1" + "ethereumjs-account": "2.0.5", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "5.2.0", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "rustbn.js": "0.1.2", + "safe-buffer": "5.1.1" }, "dependencies": { "async": { @@ -3686,7 +3683,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "ethereum-common": { @@ -3703,13 +3700,13 @@ "integrity": "sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s=", "dev": true, "requires": { - "aes-js": "^0.2.3", - "bs58check": "^1.0.8", - "ethereumjs-util": "^4.4.0", - "hdkey": "^0.7.0", - "scrypt.js": "^0.2.0", - "utf8": "^2.1.1", - "uuid": "^2.0.1" + "aes-js": "0.2.4", + "bs58check": "1.3.4", + "ethereumjs-util": "4.5.0", + "hdkey": "0.7.1", + "scrypt.js": "0.2.0", + "utf8": "2.1.2", + "uuid": "2.0.3" }, "dependencies": { "ethereumjs-util": { @@ -3718,11 +3715,11 @@ "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", "dev": true, "requires": { - "bn.js": "^4.8.0", - "create-hash": "^1.1.2", - "keccakjs": "^0.2.0", - "rlp": "^2.0.0", - "secp256k1": "^3.0.1" + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.3.0" } }, "uuid": { @@ -3792,7 +3789,7 @@ "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", "dev": true, "requires": { - "create-hash": "^1.1.1" + "create-hash": "1.1.3" } }, "execa": { @@ -3801,13 +3798,13 @@ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "exit-hook": { @@ -3822,7 +3819,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "expand-range": { @@ -3831,7 +3828,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "^2.1.0" + "fill-range": "2.2.4" } }, "expand-template": { @@ -3846,7 +3843,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "1.0.1" } }, "express": { @@ -3855,36 +3852,36 @@ "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "~1.3.5", + "accepts": "1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "~1.0.4", + "content-type": "1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.3", + "proxy-addr": "2.0.3", "qs": "6.5.1", - "range-parser": "~1.2.0", + "range-parser": "1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", + "statuses": "1.4.0", + "type-is": "1.6.16", "utils-merge": "1.0.1", - "vary": "~1.1.2" + "vary": "1.1.2" }, "dependencies": { "body-parser": { @@ -3894,15 +3891,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", + "depd": "1.1.2", + "http-errors": "1.6.3", "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "~1.6.15" + "type-is": "1.6.16" } }, "debug": { @@ -3953,7 +3950,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" + "statuses": "1.4.0" } }, "setprototypeof": { @@ -3984,8 +3981,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -3994,7 +3991,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -4005,9 +4002,9 @@ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" + "chardet": "0.4.2", + "iconv-lite": "0.4.18", + "tmp": "0.0.33" } }, "extglob": { @@ -4016,7 +4013,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "extsprintf": { @@ -4031,7 +4028,7 @@ "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", "dev": true, "requires": { - "checkpoint-store": "^1.1.0" + "checkpoint-store": "1.1.0" } }, "fast-deep-equal": { @@ -4046,12 +4043,12 @@ "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.0.1", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.1", - "micromatch": "^3.1.10" + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" }, "dependencies": { "arr-diff": { @@ -4072,16 +4069,16 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { "extend-shallow": { @@ -4090,7 +4087,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4101,13 +4098,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -4116,7 +4113,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -4125,7 +4122,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -4134,7 +4131,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4143,7 +4140,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } } } @@ -4154,7 +4151,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4163,7 +4160,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } } } @@ -4174,9 +4171,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } }, "kind-of": { @@ -4193,14 +4190,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -4209,7 +4206,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -4218,7 +4215,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4229,10 +4226,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" }, "dependencies": { "extend-shallow": { @@ -4241,7 +4238,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4252,8 +4249,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" }, "dependencies": { "is-glob": { @@ -4262,7 +4259,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" } } } @@ -4273,7 +4270,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -4282,7 +4279,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -4291,9 +4288,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, "is-extglob": { @@ -4308,7 +4305,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "2.1.1" } }, "is-number": { @@ -4317,7 +4314,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4326,7 +4323,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } } } @@ -4349,19 +4346,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } } } @@ -4384,7 +4381,7 @@ "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", "dev": true, "requires": { - "node-fetch": "~1.7.1" + "node-fetch": "1.7.3" }, "dependencies": { "node-fetch": { @@ -4393,8 +4390,8 @@ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "dev": true, "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" + "encoding": "0.1.12", + "is-stream": "1.1.0" } } } @@ -4405,7 +4402,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -4414,8 +4411,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "1.3.0", + "object-assign": "4.1.1" } }, "filename-regex": { @@ -4430,11 +4427,11 @@ "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" }, "dependencies": { "kind-of": { @@ -4449,9 +4446,9 @@ "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" }, "dependencies": { "is-number": { @@ -4471,12 +4468,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -4502,8 +4499,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" } }, "first-chunk-stream": { @@ -4512,7 +4509,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.3" } }, "flat-cache": { @@ -4521,10 +4518,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" } }, "flow-parser": { @@ -4539,7 +4536,7 @@ "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", "dev": true, "requires": { - "is-function": "~1.0.0" + "is-function": "1.0.1" } }, "for-in": { @@ -4554,7 +4551,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } }, "foreach": { @@ -4575,9 +4572,9 @@ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.18" } }, "forwarded": { @@ -4592,7 +4589,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fresh": { @@ -4607,8 +4604,8 @@ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "inherits": "2.0.3", + "readable-stream": "2.3.3" } }, "fs-extra": { @@ -4617,11 +4614,11 @@ "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.1" } }, "fs.realpath": { @@ -4637,8 +4634,8 @@ "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" }, "dependencies": { "abbrev": { @@ -4664,8 +4661,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "balanced-match": { @@ -4678,7 +4675,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -4742,7 +4739,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "fs.realpath": { @@ -4757,14 +4754,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, "glob": { @@ -4773,12 +4770,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-unicode": { @@ -4793,7 +4790,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": "2.1.2" } }, "ignore-walk": { @@ -4802,7 +4799,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "inflight": { @@ -4811,8 +4808,8 @@ "dev": true, "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -4831,7 +4828,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "isarray": { @@ -4845,7 +4842,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -4858,8 +4855,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "minizlib": { @@ -4868,7 +4865,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "mkdirp": { @@ -4891,9 +4888,9 @@ "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" } }, "node-pre-gyp": { @@ -4902,16 +4899,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" } }, "nopt": { @@ -4920,8 +4917,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "npm-bundled": { @@ -4936,8 +4933,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" } }, "npmlog": { @@ -4946,10 +4943,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -4968,7 +4965,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "os-homedir": { @@ -4989,8 +4986,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "path-is-absolute": { @@ -5011,10 +5008,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -5031,13 +5028,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "rimraf": { @@ -5046,7 +5043,7 @@ "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "safe-buffer": { @@ -5089,9 +5086,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { @@ -5100,7 +5097,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-ansi": { @@ -5108,7 +5105,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -5123,13 +5120,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "util-deprecate": { @@ -5144,7 +5141,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" } }, "wrappy": { @@ -5177,8 +5174,8 @@ "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", "dev": true, "requires": { - "source-map-support": "^0.5.3", - "webpack-cli": "^2.0.9" + "source-map-support": "0.5.4", + "webpack-cli": "2.1.5" }, "dependencies": { "source-map": { @@ -5193,7 +5190,7 @@ "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", "dev": true, "requires": { - "source-map": "^0.6.0" + "source-map": "0.6.1" } } } @@ -5204,14 +5201,14 @@ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.1.2", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, "get-caller-file": { @@ -5244,7 +5241,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "gh-got": { @@ -5253,8 +5250,8 @@ "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", "dev": true, "requires": { - "got": "^7.0.0", - "is-plain-obj": "^1.1.0" + "got": "7.1.0", + "is-plain-obj": "1.1.0" }, "dependencies": { "got": { @@ -5263,20 +5260,20 @@ "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", "dev": true, "requires": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" } }, "p-cancelable": { @@ -5291,7 +5288,7 @@ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", "dev": true, "requires": { - "p-finally": "^1.0.0" + "p-finally": "1.0.0" } }, "prepend-http": { @@ -5306,7 +5303,7 @@ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { - "prepend-http": "^1.0.1" + "prepend-http": "1.0.4" } } } @@ -5323,7 +5320,7 @@ "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", "dev": true, "requires": { - "gh-got": "^6.0.0" + "gh-got": "6.0.0" } }, "glob": { @@ -5332,12 +5329,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-all": { @@ -5346,8 +5343,8 @@ "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", "dev": true, "requires": { - "glob": "^7.0.5", - "yargs": "~1.2.6" + "glob": "7.1.2", + "yargs": "1.2.6" }, "dependencies": { "minimist": { @@ -5362,7 +5359,7 @@ "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", "dev": true, "requires": { - "minimist": "^0.1.0" + "minimist": "0.1.0" } } } @@ -5373,8 +5370,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" } }, "glob-parent": { @@ -5383,7 +5380,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "glob-to-regexp": { @@ -5398,8 +5395,8 @@ "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", "dev": true, "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" + "min-document": "2.19.0", + "process": "0.5.2" } }, "global-modules": { @@ -5408,9 +5405,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { @@ -5419,11 +5416,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "1.0.2", + "which": "1.3.0" } }, "globals": { @@ -5438,12 +5435,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "graceful-fs": { @@ -5458,7 +5455,7 @@ "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", "dev": true, "requires": { - "lodash": "^4.17.2" + "lodash": "4.17.11" } }, "growl": { @@ -5473,10 +5470,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" }, "dependencies": { "source-map": { @@ -5485,7 +5482,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } } } @@ -5502,8 +5499,8 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "has": { @@ -5512,7 +5509,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "^1.0.2" + "function-bind": "1.1.0" } }, "has-ansi": { @@ -5521,7 +5518,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "has-color": { @@ -5548,7 +5545,7 @@ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "requires": { - "has-symbol-support-x": "^1.4.1" + "has-symbol-support-x": "1.4.2" } }, "has-unicode": { @@ -5563,9 +5560,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" }, "dependencies": { "isobject": { @@ -5582,8 +5579,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "is-number": { @@ -5592,7 +5589,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -5601,7 +5598,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } } } @@ -5612,7 +5609,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } } } @@ -5623,7 +5620,7 @@ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", "dev": true, "requires": { - "inherits": "^2.0.1" + "inherits": "2.0.3" } }, "hash.js": { @@ -5632,8 +5629,8 @@ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" } }, "hdkey": { @@ -5642,8 +5639,8 @@ "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", "dev": true, "requires": { - "coinstring": "^2.0.0", - "secp256k1": "^3.0.1" + "coinstring": "2.3.0", + "secp256k1": "3.3.0" } }, "he": { @@ -5658,9 +5655,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" } }, "home-or-tmp": { @@ -5669,8 +5666,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "homedir-polyfill": { @@ -5679,7 +5676,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, "hosted-git-info": { @@ -5700,10 +5697,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "~1.1.2", + "depd": "1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "statuses": "1.5.0" } }, "http-signature": { @@ -5712,9 +5709,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "iconv-lite": { @@ -5741,8 +5738,8 @@ "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "pkg-dir": "^2.0.0", - "resolve-cwd": "^2.0.0" + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" }, "dependencies": { "find-up": { @@ -5751,7 +5748,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "pkg-dir": { @@ -5760,7 +5757,7 @@ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "^2.1.0" + "find-up": "2.1.0" } } } @@ -5777,7 +5774,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "inflight": { @@ -5786,8 +5783,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -5808,20 +5805,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.11", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" }, "dependencies": { "ansi-regex": { @@ -5836,7 +5833,7 @@ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "chalk": { @@ -5845,9 +5842,9 @@ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" } }, "has-flag": { @@ -5868,8 +5865,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -5878,7 +5875,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -5887,7 +5884,7 @@ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "^2.0.0" + "has-flag": "2.0.0" } } } @@ -5904,8 +5901,8 @@ "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "dev": true, "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" + "from2": "2.3.0", + "p-is-promise": "1.1.0" } }, "invariant": { @@ -5914,7 +5911,7 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.3.1" } }, "invert-kv": { @@ -5935,7 +5932,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "is-arrayish": { @@ -5950,7 +5947,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.11.0" } }, "is-buffer": { @@ -5965,7 +5962,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-callable": { @@ -5980,7 +5977,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "is-date-object": { @@ -5995,9 +5992,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -6020,7 +6017,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "is-primitive": "2.0.0" } }, "is-extendable": { @@ -6041,7 +6038,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-fn": { @@ -6056,7 +6053,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-function": { @@ -6071,7 +6068,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "is-hex-prefixed": { @@ -6086,7 +6083,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "is-object": { @@ -6107,7 +6104,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { @@ -6116,7 +6113,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-plain-obj": { @@ -6131,7 +6128,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" }, "dependencies": { "isobject": { @@ -6166,7 +6163,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "^1.0.1" + "has": "1.0.1" } }, "is-resolvable": { @@ -6187,7 +6184,7 @@ "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", "dev": true, "requires": { - "scoped-regex": "^1.0.0" + "scoped-regex": "1.0.0" } }, "is-stream": { @@ -6259,20 +6256,20 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.6.1", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" }, "dependencies": { "glob": { @@ -6281,11 +6278,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-flag": { @@ -6306,7 +6303,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -6317,9 +6314,9 @@ "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", "dev": true, "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" } }, "isurl": { @@ -6328,8 +6325,8 @@ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" } }, "js-sha3": { @@ -6356,8 +6353,8 @@ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" + "argparse": "1.0.10", + "esprima": "2.7.3" } }, "jsbn": { @@ -6373,21 +6370,21 @@ "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", "dev": true, "requires": { - "babel-plugin-transform-flow-strip-types": "^6.8.0", - "babel-preset-es2015": "^6.9.0", - "babel-preset-stage-1": "^6.5.0", - "babel-register": "^6.9.0", - "babylon": "^7.0.0-beta.47", - "colors": "^1.1.2", - "flow-parser": "^0.*", - "lodash": "^4.13.1", - "micromatch": "^2.3.7", - "neo-async": "^2.5.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.1.2", + "flow-parser": "0.69.0", + "lodash": "4.17.11", + "micromatch": "2.3.11", + "neo-async": "2.5.0", "node-dir": "0.1.8", - "nomnom": "^1.8.1", - "recast": "^0.15.0", - "temp": "^0.8.1", - "write-file-atomic": "^1.2.0" + "nomnom": "1.8.1", + "recast": "0.15.0", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" }, "dependencies": { "ast-types": { @@ -6415,9 +6412,9 @@ "dev": true, "requires": { "ast-types": "0.11.5", - "esprima": "~4.0.0", - "private": "~0.1.5", - "source-map": "~0.6.1" + "esprima": "4.0.0", + "private": "0.1.7", + "source-map": "0.6.1" } }, "source-map": { @@ -6452,12 +6449,12 @@ "integrity": "sha512-+FO3UWu/wafh/+MZ6BXy0HZU+f5plwUn82FgxpC0scJkEh5snOjFrAAtqCITPDfvfLHRUFOG5pQDUx2pspfERQ==", "dev": true, "requires": { - "async": "^2.0.1", - "babel-preset-env": "^1.3.2", - "babelify": "^7.3.0", - "clone": "^2.1.1", - "json-rpc-error": "^2.0.0", - "promise-to-callback": "^1.0.0" + "async": "2.6.1", + "babel-preset-env": "1.7.0", + "babelify": "7.3.0", + "clone": "2.1.1", + "json-rpc-error": "2.0.0", + "promise-to-callback": "1.0.0" }, "dependencies": { "async": { @@ -6466,7 +6463,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } } } @@ -6477,7 +6474,7 @@ "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", "dev": true, "requires": { - "inherits": "^2.0.1" + "inherits": "2.0.3" } }, "json-rpc-random-id": { @@ -6504,7 +6501,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json-stable-stringify-without-jsonify": { @@ -6531,7 +6528,7 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "4.1.11" } }, "jsonify": { @@ -6558,11 +6555,11 @@ "integrity": "sha512-JgsKPxYhcJxKrV+TrCyg/GwZbOjhpRPrz2kG8xbAsUaIDelUlKjm08YcwBO9Fm8sqf/Kg8ZWkk6nWujhLykfvw==", "dev": true, "requires": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "prebuild-install": "^2.0.0", - "safe-buffer": "^5.1.0" + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "prebuild-install": "2.2.2", + "safe-buffer": "5.1.1" } }, "keccakjs": { @@ -6571,8 +6568,8 @@ "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", "dev": true, "requires": { - "browserify-sha3": "^0.0.1", - "sha3": "^1.1.0" + "browserify-sha3": "0.0.1", + "sha3": "1.2.2" } }, "keyv": { @@ -6590,7 +6587,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.5" } }, "klaw": { @@ -6599,7 +6596,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "graceful-fs": "4.1.11" } }, "lazy-cache": { @@ -6615,7 +6612,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "1.0.0" } }, "lcov-parse": { @@ -6636,7 +6633,7 @@ "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", "dev": true, "requires": { - "errno": "~0.1.1" + "errno": "0.1.4" } }, "level-iterator-stream": { @@ -6645,10 +6642,10 @@ "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", "dev": true, "requires": { - "inherits": "^2.0.1", - "level-errors": "^1.0.3", - "readable-stream": "^1.0.33", - "xtend": "^4.0.0" + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" }, "dependencies": { "isarray": { @@ -6663,10 +6660,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -6683,8 +6680,8 @@ "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", "dev": true, "requires": { - "readable-stream": "~1.0.15", - "xtend": "~2.1.1" + "readable-stream": "1.0.34", + "xtend": "2.1.2" }, "dependencies": { "isarray": { @@ -6705,10 +6702,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -6723,7 +6720,7 @@ "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dev": true, "requires": { - "object-keys": "~0.4.0" + "object-keys": "0.4.0" } } } @@ -6734,13 +6731,13 @@ "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", "dev": true, "requires": { - "deferred-leveldown": "~1.2.1", - "level-codec": "~7.0.0", - "level-errors": "~1.0.3", - "level-iterator-stream": "~1.3.0", - "prr": "~1.0.1", - "semver": "~5.4.1", - "xtend": "~4.0.0" + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" } }, "levn": { @@ -6749,8 +6746,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "listr-silent-renderer": { @@ -6765,14 +6762,14 @@ "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "strip-ansi": "^3.0.1" + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "figures": { @@ -6781,8 +6778,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "indent-string": { @@ -6797,7 +6794,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "^1.0.0" + "chalk": "1.1.3" } } } @@ -6808,10 +6805,10 @@ "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-cursor": "^1.0.2", - "date-fns": "^1.27.2", - "figures": "^1.7.0" + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" }, "dependencies": { "cli-cursor": { @@ -6820,7 +6817,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "figures": { @@ -6829,8 +6826,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "onetime": { @@ -6845,8 +6842,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } } } @@ -6857,11 +6854,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" } }, "loader-utils": { @@ -6870,9 +6867,9 @@ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" } }, "locate-path": { @@ -6881,8 +6878,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" }, "dependencies": { "path-exists": { @@ -6917,7 +6914,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "^2.0.1" + "chalk": "2.3.2" }, "dependencies": { "ansi-styles": { @@ -6926,7 +6923,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "chalk": { @@ -6935,9 +6932,9 @@ "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" } }, "has-flag": { @@ -6952,7 +6949,7 @@ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -6963,8 +6960,8 @@ "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", "dev": true, "requires": { - "ansi-escapes": "^1.0.0", - "cli-cursor": "^1.0.2" + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" }, "dependencies": { "ansi-escapes": { @@ -6979,7 +6976,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "onetime": { @@ -6994,8 +6991,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } } } @@ -7012,7 +7009,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "^3.0.0" + "js-tokens": "3.0.2" } }, "lowercase-keys": { @@ -7033,7 +7030,7 @@ "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" }, "dependencies": { "pify": { @@ -7056,7 +7053,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "math-random": { @@ -7077,7 +7074,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.1.0" } }, "mem-fs": { @@ -7086,9 +7083,9 @@ "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", "dev": true, "requires": { - "through2": "^2.0.0", - "vinyl": "^1.1.0", - "vinyl-file": "^2.0.0" + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" } }, "memdown": { @@ -7097,12 +7094,12 @@ "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", "dev": true, "requires": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.1" }, "dependencies": { "abstract-leveldown": { @@ -7111,7 +7108,7 @@ "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", "dev": true, "requires": { - "xtend": "~4.0.0" + "xtend": "4.0.1" } } } @@ -7122,8 +7119,8 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "errno": "0.1.4", + "readable-stream": "2.3.3" } }, "memorystream": { @@ -7150,14 +7147,14 @@ "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", "dev": true, "requires": { - "async": "^1.4.2", - "ethereumjs-util": "^5.0.0", + "async": "1.5.2", + "ethereumjs-util": "5.2.0", "level-ws": "0.0.0", - "levelup": "^1.2.1", - "memdown": "^1.0.0", - "readable-stream": "^2.0.0", - "rlp": "^2.0.0", - "semaphore": ">=1.0.1" + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.3", + "rlp": "2.0.0", + "semaphore": "1.1.0" } }, "methods": { @@ -7172,19 +7169,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" } }, "mime": { @@ -7205,7 +7202,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "1.33.0" } }, "mimic-fn": { @@ -7226,7 +7223,7 @@ "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", "dev": true, "requires": { - "dom-walk": "^0.1.0" + "dom-walk": "0.1.1" } }, "minimalistic-assert": { @@ -7247,7 +7244,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.8" } }, "minimist": { @@ -7262,8 +7259,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -7272,7 +7269,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -7325,7 +7322,7 @@ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "has-flag": "^2.0.0" + "has-flag": "2.0.0" } } } @@ -7342,10 +7339,10 @@ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" } }, "mute-stream": { @@ -7372,17 +7369,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "arr-diff": { @@ -7453,8 +7450,8 @@ "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", "dev": true, "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" + "chalk": "0.4.0", + "underscore": "1.6.0" }, "dependencies": { "ansi-styles": { @@ -7469,9 +7466,9 @@ "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" } }, "strip-ansi": { @@ -7494,7 +7491,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.0.9" } }, "normalize-package-data": { @@ -7503,10 +7500,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" } }, "normalize-path": { @@ -7515,7 +7512,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.0.2" } }, "normalize-url": { @@ -7524,9 +7521,9 @@ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", "dev": true, "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" } }, "npm-run-path": { @@ -7535,7 +7532,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "npmlog": { @@ -7544,10 +7541,10 @@ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -7592,9 +7589,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -7603,7 +7600,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -7626,7 +7623,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" }, "dependencies": { "isobject": { @@ -7643,8 +7640,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "for-own": "0.1.5", + "is-extendable": "0.1.1" } }, "object.pick": { @@ -7653,7 +7650,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" }, "dependencies": { "isobject": { @@ -7679,7 +7676,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -7688,7 +7685,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.1.0" } }, "optimist": { @@ -7697,8 +7694,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.8", + "wordwrap": "0.0.3" }, "dependencies": { "wordwrap": { @@ -7715,12 +7712,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" } }, "ora": { @@ -7729,10 +7726,10 @@ "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", "dev": true, "requires": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" }, "dependencies": { "cli-cursor": { @@ -7741,7 +7738,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "onetime": { @@ -7756,8 +7753,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } } } @@ -7780,7 +7777,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "^1.0.0" + "lcid": "1.0.0" } }, "os-tmpdir": { @@ -7801,7 +7798,7 @@ "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "requires": { - "p-reduce": "^1.0.0" + "p-reduce": "1.0.0" } }, "p-finally": { @@ -7834,7 +7831,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "1.1.0" } }, "p-map": { @@ -7855,7 +7852,7 @@ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", "dev": true, "requires": { - "p-finally": "^1.0.0" + "p-finally": "1.0.0" } }, "parse-glob": { @@ -7864,10 +7861,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" } }, "parse-headers": { @@ -7876,7 +7873,7 @@ "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", "dev": true, "requires": { - "for-each": "^0.3.2", + "for-each": "0.3.2", "trim": "0.0.1" } }, @@ -7886,7 +7883,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "1.3.1" } }, "parse-passwd": { @@ -7919,7 +7916,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "pinkie-promise": "2.0.1" } }, "path-is-absolute": { @@ -7958,9 +7955,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pathval": { @@ -7975,11 +7972,11 @@ "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" } }, "pegjs": { @@ -8012,7 +8009,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "pkg-dir": { @@ -8021,7 +8018,7 @@ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "^1.0.0" + "find-up": "1.1.2" } }, "pluralize": { @@ -8042,19 +8039,19 @@ "integrity": "sha512-F46pcvDxtQhbV3B+dm+exHuKxIyJK26fVNiJRmbTW/5D7o0Z2yzc8CKeu7UWbo9XxQZoVOC88aKgySAsza+cWw==", "dev": true, "requires": { - "expand-template": "^1.0.2", + "expand-template": "1.0.3", "github-from-package": "0.0.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "node-abi": "^2.0.0", - "noop-logger": "^0.1.1", - "npmlog": "^4.0.1", - "os-homedir": "^1.0.1", - "pump": "^1.0.1", - "rc": "^1.1.6", - "simple-get": "^1.4.2", - "tar-fs": "^1.13.0", - "tunnel-agent": "^0.6.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.1.0", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "1.0.2", + "rc": "1.2.8", + "simple-get": "1.4.3", + "tar-fs": "1.15.3", + "tunnel-agent": "0.6.0", "xtend": "4.0.1" }, "dependencies": { @@ -8070,7 +8067,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.1" } } } @@ -8135,8 +8132,8 @@ "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", "dev": true, "requires": { - "is-fn": "^1.0.0", - "set-immediate-shim": "^1.0.1" + "is-fn": "1.0.0", + "set-immediate-shim": "1.0.1" } }, "proxy-addr": { @@ -8145,7 +8142,7 @@ "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "dev": true, "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.1.2", "ipaddr.js": "1.6.0" } }, @@ -8167,8 +8164,8 @@ "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.0", + "once": "1.4.0" } }, "punycode": { @@ -8189,9 +8186,9 @@ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" } }, "randombytes": { @@ -8200,7 +8197,7 @@ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { - "safe-buffer": "^5.1.0" + "safe-buffer": "5.1.1" } }, "randomhex": { @@ -8233,7 +8230,7 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } } } @@ -8244,10 +8241,10 @@ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.6.0", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "deep-extend": { @@ -8270,8 +8267,8 @@ "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", "dev": true, "requires": { - "pify": "^3.0.0", - "safe-buffer": "^5.1.1" + "pify": "3.0.0", + "safe-buffer": "5.1.1" }, "dependencies": { "pify": { @@ -8288,9 +8285,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" } }, "read-pkg-up": { @@ -8299,8 +8296,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" } }, "readable-stream": { @@ -8309,13 +8306,13 @@ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "readdirp": { @@ -8324,10 +8321,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" } }, "rechoir": { @@ -8336,7 +8333,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "1.4.0" } }, "regenerate": { @@ -8357,9 +8354,9 @@ "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" + "babel-runtime": "6.25.0", + "babel-types": "6.25.0", + "private": "0.1.7" } }, "regex-cache": { @@ -8368,8 +8365,8 @@ "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3", - "is-primitive": "^2.0.0" + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" } }, "regex-not": { @@ -8378,8 +8375,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "regexpp": { @@ -8394,9 +8391,9 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "1.3.2", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" } }, "regjsgen": { @@ -8411,7 +8408,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "~0.5.0" + "jsesc": "0.5.0" } }, "remove-trailing-separator": { @@ -8438,7 +8435,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "replace-ext": { @@ -8453,7 +8450,7 @@ "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", "dev": true, "requires": { - "req-from": "^1.0.1" + "req-from": "1.0.1" } }, "req-from": { @@ -8462,7 +8459,7 @@ "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", "dev": true, "requires": { - "resolve-from": "^2.0.0" + "resolve-from": "2.0.0" }, "dependencies": { "resolve-from": { @@ -8479,26 +8476,26 @@ "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "dev": true, "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.1", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.0" } }, "require-directory": { @@ -8525,8 +8522,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" } }, "requireindex": { @@ -8541,7 +8538,7 @@ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } }, "resolve-cwd": { @@ -8550,7 +8547,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "3.0.0" }, "dependencies": { "resolve-from": { @@ -8567,8 +8564,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, "resolve-from": { @@ -8589,7 +8586,7 @@ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "dev": true, "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "1.0.1" } }, "restore-cursor": { @@ -8598,8 +8595,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "resumer": { @@ -8608,7 +8605,7 @@ "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", "dev": true, "requires": { - "through": "~2.3.4" + "through": "2.3.8" } }, "ret": { @@ -8624,7 +8621,7 @@ "dev": true, "optional": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -8633,7 +8630,7 @@ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "ripemd160": { @@ -8642,8 +8639,8 @@ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", "dev": true, "requires": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "hash-base": "2.0.2", + "inherits": "2.0.3" } }, "rlp": { @@ -8658,7 +8655,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "^2.1.0" + "is-promise": "2.1.0" } }, "rustbn.js": { @@ -8679,7 +8676,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "*" + "rx-lite": "4.0.8" } }, "rxjs": { @@ -8703,7 +8700,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "safer-buffer": { @@ -8724,7 +8721,7 @@ "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", "dev": true, "requires": { - "nan": "^2.0.8" + "nan": "2.10.0" } }, "scrypt.js": { @@ -8733,8 +8730,8 @@ "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", "dev": true, "requires": { - "scrypt": "^6.0.2", - "scryptsy": "^1.2.1" + "scrypt": "6.0.3", + "scryptsy": "1.2.1" } }, "scryptsy": { @@ -8743,7 +8740,7 @@ "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", "dev": true, "requires": { - "pbkdf2": "^3.0.3" + "pbkdf2": "3.0.16" } }, "secp256k1": { @@ -8752,15 +8749,15 @@ "integrity": "sha512-CbrQoeGG5V0kQ1ohEMGI+J7oKerapLTpivLICBaXR0R4HyQcN3kM9itLsV5fdpV1UR1bD14tOkJ1xughmlDIiQ==", "dev": true, "requires": { - "bindings": "^1.2.1", - "bip66": "^1.1.3", - "bn.js": "^4.11.3", - "create-hash": "^1.1.2", - "drbg.js": "^1.0.1", - "elliptic": "^6.2.3", - "nan": "^2.2.1", - "prebuild-install": "^2.0.0", - "safe-buffer": "^5.1.0" + "bindings": "1.3.0", + "bip66": "1.1.5", + "bn.js": "4.11.8", + "create-hash": "1.1.3", + "drbg.js": "1.0.1", + "elliptic": "6.4.0", + "nan": "2.10.0", + "prebuild-install": "2.2.2", + "safe-buffer": "5.1.1" } }, "semaphore": { @@ -8782,18 +8779,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", "fresh": "0.5.2", - "http-errors": "~1.6.2", + "http-errors": "1.6.3", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" }, "dependencies": { "debug": { @@ -8819,9 +8816,9 @@ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", "send": "0.16.2" } }, @@ -8831,11 +8828,11 @@ "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", "dev": true, "requires": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" + "body-parser": "1.18.3", + "cors": "2.8.4", + "express": "4.16.3", + "request": "2.87.0", + "xhr": "2.4.0" } }, "set-blocking": { @@ -8856,10 +8853,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -8868,7 +8865,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -8885,7 +8882,7 @@ "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", "dev": true, "requires": { - "inherits": "^2.0.1" + "inherits": "2.0.3" } }, "sha3": { @@ -8903,7 +8900,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -8918,9 +8915,9 @@ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "glob": "7.1.2", + "interpret": "1.0.3", + "rechoir": "0.6.2" } }, "signal-exit": { @@ -8941,9 +8938,9 @@ "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", "dev": true, "requires": { - "once": "^1.3.1", - "unzip-response": "^1.0.0", - "xtend": "^4.0.0" + "once": "1.4.0", + "unzip-response": "1.0.2", + "xtend": "4.0.1" } }, "slash": { @@ -8958,7 +8955,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0" + "is-fullwidth-code-point": "2.0.0" }, "dependencies": { "is-fullwidth-code-point": { @@ -8981,14 +8978,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" }, "dependencies": { "define-property": { @@ -8997,7 +8994,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -9006,7 +9003,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -9017,9 +9014,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -9028,7 +9025,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -9037,7 +9034,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -9046,7 +9043,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -9055,9 +9052,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, "isobject": { @@ -9080,7 +9077,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" } }, "sol-digger": { @@ -9101,11 +9098,11 @@ "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", "dev": true, "requires": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" }, "dependencies": { "yargs": { @@ -9114,20 +9111,20 @@ "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" } } } @@ -9138,16 +9135,16 @@ "integrity": "sha512-UvjLBgUJiLvufU6K9xmf/gPIU7DhWcDmBA6iTJ0dZI7LsvU+vugN1/ByZojU54kWLpaODx0A+P4cIT0jcRVNNw==", "dev": true, "requires": { - "death": "^1.1.0", + "death": "1.1.0", "ethereumjs-testrpc-sc": "6.1.2", - "istanbul": "^0.4.5", - "keccakjs": "^0.2.1", - "req-cwd": "^1.0.1", - "shelljs": "^0.7.4", - "sol-explore": "^1.6.2", + "istanbul": "0.4.5", + "keccakjs": "0.2.1", + "req-cwd": "1.0.1", + "shelljs": "0.7.8", + "sol-explore": "1.6.2", "solidity-parser-sc": "0.4.10", - "tree-kill": "^1.2.0", - "web3": "^0.18.4" + "tree-kill": "1.2.0", + "web3": "0.18.4" } }, "solidity-parser-sc": { @@ -9156,9 +9153,9 @@ "integrity": "sha512-oGgFpeX4OzvOfku/Bnw3/yrOmcVJTgXa994HjZwWXA/kHVZ4L1ml9BcbWHRAziJYm3ObHCXlKumfMCBXBt9K8Q==", "dev": true, "requires": { - "mocha": "^4.1.0", - "pegjs": "^0.10.0", - "yargs": "^4.6.0" + "mocha": "4.1.0", + "pegjs": "0.10.0", + "yargs": "4.8.1" }, "dependencies": { "yargs": { @@ -9167,20 +9164,20 @@ "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" } } } @@ -9191,18 +9188,18 @@ "integrity": "sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA==", "dev": true, "requires": { - "ajv": "^5.2.2", - "chokidar": "^1.6.0", - "colors": "^1.1.2", - "commander": "^2.9.0", - "eol": "^0.9.1", - "js-string-escape": "^1.0.1", - "lodash": "^4.14.2", + "ajv": "5.5.2", + "chokidar": "1.7.0", + "colors": "1.1.2", + "commander": "2.11.0", + "eol": "0.9.1", + "js-string-escape": "1.0.1", + "lodash": "4.17.11", "sol-digger": "0.0.2", "sol-explore": "1.6.1", "solium-plugin-security": "0.1.1", "solparse": "2.2.5", - "text-table": "^0.2.0" + "text-table": "0.2.0" }, "dependencies": { "ansi-regex": { @@ -9223,9 +9220,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" } }, "find-up": { @@ -9234,7 +9231,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "is-fullwidth-code-point": { @@ -9249,9 +9246,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "sol-explore": { @@ -9266,9 +9263,9 @@ "integrity": "sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA==", "dev": true, "requires": { - "mocha": "^4.0.1", - "pegjs": "^0.10.0", - "yargs": "^10.0.3" + "mocha": "4.1.0", + "pegjs": "0.10.0", + "yargs": "10.1.2" } }, "string-width": { @@ -9277,8 +9274,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -9287,7 +9284,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "which-module": { @@ -9302,18 +9299,18 @@ "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.1.0" } }, "yargs-parser": { @@ -9322,7 +9319,7 @@ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" } } } @@ -9339,7 +9336,7 @@ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } }, "source-map": { @@ -9354,11 +9351,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-support": { @@ -9367,7 +9364,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "^0.5.6" + "source-map": "0.5.7" } }, "source-map-url": { @@ -9382,7 +9379,7 @@ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", "dev": true, "requires": { - "spdx-license-ids": "^1.0.2" + "spdx-license-ids": "1.2.2" } }, "spdx-expression-parse": { @@ -9403,7 +9400,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -9418,15 +9415,15 @@ "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "static-extend": { @@ -9435,8 +9432,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -9445,7 +9442,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -9474,9 +9471,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string.prototype.trim": { @@ -9485,9 +9482,9 @@ "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.0", - "function-bind": "^1.0.2" + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.0" } }, "string_decoder": { @@ -9496,7 +9493,7 @@ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-ansi": { @@ -9505,7 +9502,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-bom": { @@ -9514,7 +9511,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -9523,8 +9520,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" } }, "strip-eof": { @@ -9566,12 +9563,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.11", "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "string-width": "2.1.1" }, "dependencies": { "ansi-regex": { @@ -9586,7 +9583,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "chalk": { @@ -9595,9 +9592,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "is-fullwidth-code-point": { @@ -9612,8 +9609,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -9622,7 +9619,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -9631,7 +9628,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -9648,19 +9645,19 @@ "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", "dev": true, "requires": { - "deep-equal": "~1.0.1", - "defined": "~1.0.0", - "for-each": "~0.3.3", - "function-bind": "~1.1.1", - "glob": "~7.1.2", - "has": "~1.0.3", - "inherits": "~2.0.3", - "minimist": "~1.2.0", - "object-inspect": "~1.6.0", - "resolve": "~1.7.1", - "resumer": "~0.0.0", - "string.prototype.trim": "~1.1.2", - "through": "~2.3.8" + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.3", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.3", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.6.0", + "resolve": "1.7.1", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" }, "dependencies": { "for-each": { @@ -9669,7 +9666,7 @@ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "requires": { - "is-callable": "^1.1.3" + "is-callable": "1.1.3" } }, "function-bind": { @@ -9684,7 +9681,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "1.1.1" } }, "minimist": { @@ -9699,7 +9696,7 @@ "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } } } @@ -9710,10 +9707,10 @@ "integrity": "sha1-7M+TXpQUk9gVECjmNuUc5MPKfyA=", "dev": true, "requires": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.2", + "tar-stream": "1.5.4" } }, "tar-stream": { @@ -9722,10 +9719,10 @@ "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", "dev": true, "requires": { - "bl": "^1.0.0", - "end-of-stream": "^1.0.0", - "readable-stream": "^2.0.0", - "xtend": "^4.0.0" + "bl": "1.2.1", + "end-of-stream": "1.4.0", + "readable-stream": "2.3.3", + "xtend": "4.0.1" } }, "temp": { @@ -9734,8 +9731,8 @@ "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "dev": true, "requires": { - "os-tmpdir": "^1.0.0", - "rimraf": "~2.2.6" + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" }, "dependencies": { "rimraf": { @@ -9770,8 +9767,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.3", + "xtend": "4.0.1" } }, "timed-out": { @@ -9786,7 +9783,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "os-tmpdir": "1.0.2" } }, "to-fast-properties": { @@ -9801,7 +9798,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "to-regex": { @@ -9810,10 +9807,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -9822,8 +9819,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" }, "dependencies": { "is-number": { @@ -9832,7 +9829,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } } } @@ -9843,7 +9840,7 @@ "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "punycode": "^1.4.1" + "punycode": "1.4.1" } }, "tree-kill": { @@ -9876,7 +9873,7 @@ "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", "dev": true, "requires": { - "mocha": "^4.1.0", + "mocha": "4.1.0", "original-require": "1.0.1", "solc": "0.4.24" } @@ -9887,10 +9884,10 @@ "integrity": "sha512-dVVcHIOy7DRwVs+BeDt39pvHnHak1zb1BQ30pHaux7fmxk/T/TJVKp18D584qCWnCbnSt8bMdB3XxALPLXIbVw==", "dev": true, "requires": { - "bip39": "^2.2.0", - "ethereumjs-wallet": "^0.6.0", - "web3": "^0.18.2", - "web3-provider-engine": "^14.0.5" + "bip39": "2.5.0", + "ethereumjs-wallet": "0.6.0", + "web3": "0.18.4", + "web3-provider-engine": "14.0.6" } }, "tslib": { @@ -9905,7 +9902,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.1" } }, "tweetnacl": { @@ -9921,7 +9918,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "type-detect": { @@ -9937,7 +9934,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "2.1.18" }, "dependencies": { "mime-db": { @@ -9952,7 +9949,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "1.33.0" } } } @@ -9970,9 +9967,9 @@ "dev": true, "optional": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" } }, "uglify-to-browserify": { @@ -10000,10 +9997,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -10012,7 +10009,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -10021,10 +10018,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -10047,8 +10044,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -10057,9 +10054,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -10111,7 +10108,7 @@ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, "requires": { - "prepend-http": "^2.0.0" + "prepend-http": "2.0.0" } }, "url-set-query": { @@ -10132,7 +10129,7 @@ "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { - "kind-of": "^6.0.2" + "kind-of": "6.0.2" }, "dependencies": { "kind-of": { @@ -10173,8 +10170,8 @@ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", "dev": true, "requires": { - "spdx-correct": "~1.0.0", - "spdx-expression-parse": "~1.0.0" + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" } }, "vary": { @@ -10189,9 +10186,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "vinyl": { @@ -10200,8 +10197,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -10219,12 +10216,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" } }, "web3": { @@ -10234,10 +10231,10 @@ "dev": true, "requires": { "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "^3.1.4", - "utf8": "^2.1.1", - "xhr2": "*", - "xmlhttprequest": "*" + "crypto-js": "3.1.8", + "utf8": "2.1.2", + "xhr2": "0.1.4", + "xmlhttprequest": "1.8.0" } }, "web3-provider-engine": { @@ -10246,27 +10243,27 @@ "integrity": "sha512-tr5cGSyxfSC/JqiUpBlJtfZpwQf1yAA8L/zy1C6fDFm0ntR974pobJ4v4676atpZne4Ze5VFy3kPPahHe9gQiQ==", "dev": true, "requires": { - "async": "^2.5.0", - "backoff": "^2.5.0", - "clone": "^2.0.0", - "cross-fetch": "^2.1.0", - "eth-block-tracker": "^3.0.0", - "eth-json-rpc-infura": "^3.1.0", - "eth-sig-util": "^1.4.2", - "ethereumjs-block": "^1.2.2", - "ethereumjs-tx": "^1.2.0", - "ethereumjs-util": "^5.1.5", - "ethereumjs-vm": "^2.3.4", - "json-rpc-error": "^2.0.0", - "json-stable-stringify": "^1.0.1", - "promise-to-callback": "^1.0.0", - "readable-stream": "^2.2.9", - "request": "^2.67.0", - "semaphore": "^1.0.3", - "tape": "^4.4.0", - "ws": "^5.1.1", - "xhr": "^2.2.0", - "xtend": "^4.0.1" + "async": "2.6.1", + "backoff": "2.5.0", + "clone": "2.1.1", + "cross-fetch": "2.2.1", + "eth-block-tracker": "3.0.1", + "eth-json-rpc-infura": "3.1.2", + "eth-sig-util": "1.4.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.5", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.5", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "readable-stream": "2.3.3", + "request": "2.87.0", + "semaphore": "1.1.0", + "tape": "4.9.1", + "ws": "5.2.1", + "xhr": "2.4.0", + "xtend": "4.0.1" }, "dependencies": { "async": { @@ -10275,7 +10272,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "ws": { @@ -10284,7 +10281,7 @@ "integrity": "sha512-2NkHdPKjDBj3CHdnAGNpmlliryKqF+n9MYXX7/wsVC4yqYocKreKNjydPDvT3wShAZnndlM0RytEfTALCDvz7A==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "1.0.0" } } } @@ -10330,7 +10327,7 @@ "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", "dev": true, "requires": { - "jscodeshift": "^0.4.0" + "jscodeshift": "0.4.1" }, "dependencies": { "ast-types": { @@ -10351,21 +10348,21 @@ "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", "dev": true, "requires": { - "async": "^1.5.0", - "babel-plugin-transform-flow-strip-types": "^6.8.0", - "babel-preset-es2015": "^6.9.0", - "babel-preset-stage-1": "^6.5.0", - "babel-register": "^6.9.0", - "babylon": "^6.17.3", - "colors": "^1.1.2", - "flow-parser": "^0.*", - "lodash": "^4.13.1", - "micromatch": "^2.3.7", + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.17.4", + "colors": "1.1.2", + "flow-parser": "0.69.0", + "lodash": "4.17.11", + "micromatch": "2.3.11", "node-dir": "0.1.8", - "nomnom": "^1.8.1", - "recast": "^0.12.5", - "temp": "^0.8.1", - "write-file-atomic": "^1.2.0" + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" } }, "recast": { @@ -10375,10 +10372,10 @@ "dev": true, "requires": { "ast-types": "0.10.1", - "core-js": "^2.4.1", - "esprima": "~4.0.0", - "private": "~0.1.5", - "source-map": "~0.6.1" + "core-js": "2.5.0", + "esprima": "4.0.0", + "private": "0.1.7", + "source-map": "0.6.1" } }, "source-map": { @@ -10395,32 +10392,32 @@ "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", "dev": true, "requires": { - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "diff": "^3.5.0", - "enhanced-resolve": "^4.0.0", - "envinfo": "^5.7.0", - "glob-all": "^3.1.0", - "global-modules": "^1.0.0", - "got": "^8.3.1", - "import-local": "^1.0.0", - "inquirer": "^5.2.0", - "interpret": "^1.1.0", - "jscodeshift": "^0.5.0", - "listr": "^0.14.1", - "loader-utils": "^1.1.0", - "lodash": "^4.17.10", - "log-symbols": "^2.2.0", - "mkdirp": "^0.5.1", - "p-each-series": "^1.0.0", - "p-lazy": "^1.0.0", - "prettier": "^1.12.1", - "supports-color": "^5.4.0", - "v8-compile-cache": "^2.0.0", - "webpack-addons": "^1.1.5", - "yargs": "^11.1.0", - "yeoman-environment": "^2.1.1", - "yeoman-generator": "^2.0.5" + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.1.0", + "envinfo": "5.10.0", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.1", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.1", + "listr": "0.14.1", + "loader-utils": "1.1.0", + "lodash": "4.17.11", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.13.6", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.3.0", + "yeoman-generator": "2.0.5" }, "dependencies": { "ansi-regex": { @@ -10435,7 +10432,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "async": { @@ -10444,7 +10441,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "camelcase": { @@ -10459,9 +10456,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "cliui": { @@ -10470,9 +10467,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" } }, "clone-stats": { @@ -10487,11 +10484,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" } }, "debug": { @@ -10533,7 +10530,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "globby": { @@ -10542,13 +10539,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" } }, "got": { @@ -10557,23 +10554,23 @@ "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", "dev": true, "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "into-stream": "3.1.0", + "is-retry-allowed": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "mimic-response": "1.0.0", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "url-parse-lax": "3.0.0", + "url-to-options": "1.0.1" } }, "inquirer": { @@ -10582,19 +10579,19 @@ "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.1.0", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.0.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.11", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^5.5.2", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rxjs": "5.5.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, "interpret": { @@ -10615,7 +10612,7 @@ "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dev": true, "requires": { - "symbol-observable": "^1.1.0" + "symbol-observable": "1.2.0" } }, "listr": { @@ -10624,22 +10621,22 @@ "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", "dev": true, "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "cli-truncate": "^0.2.1", - "figures": "^1.7.0", - "indent-string": "^2.1.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.4.0", - "listr-verbose-renderer": "^0.4.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "ora": "^0.2.3", - "p-map": "^1.1.1", - "rxjs": "^6.1.0", - "strip-ansi": "^3.0.1" + "@samverschueren/stream-to-observable": "0.3.0", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "1.1.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "6.2.1", + "strip-ansi": "3.0.1" }, "dependencies": { "ansi-regex": { @@ -10660,11 +10657,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "figures": { @@ -10673,8 +10670,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "log-symbols": { @@ -10683,7 +10680,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "^1.0.0" + "chalk": "1.1.3" } }, "rxjs": { @@ -10692,7 +10689,7 @@ "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", "dev": true, "requires": { - "tslib": "^1.9.0" + "tslib": "1.9.3" } }, "strip-ansi": { @@ -10701,7 +10698,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "supports-color": { @@ -10718,10 +10715,10 @@ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" } }, "mem-fs-editor": { @@ -10730,17 +10727,17 @@ "integrity": "sha512-QHvdXLLNmwJXxKdf7x27aNUren6IoPxwcM8Sfd+S6/ddQQMcYdEtVKsh6ilpqMrU18VQuKZEaH0aCGt3JDbA0g==", "dev": true, "requires": { - "commondir": "^1.0.1", - "deep-extend": "^0.5.1", - "ejs": "^2.5.9", - "glob": "^7.0.3", - "globby": "^8.0.0", - "isbinaryfile": "^3.0.2", - "mkdirp": "^0.5.0", - "multimatch": "^2.0.0", - "rimraf": "^2.2.8", - "through2": "^2.0.0", - "vinyl": "^2.0.1" + "commondir": "1.0.1", + "deep-extend": "0.5.1", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "8.0.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.6.2", + "through2": "2.0.3", + "vinyl": "2.2.0" } }, "minimist": { @@ -10755,9 +10752,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "parse-json": { @@ -10766,8 +10763,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" } }, "path-type": { @@ -10776,7 +10773,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "pify": { @@ -10797,9 +10794,9 @@ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" } }, "read-pkg-up": { @@ -10808,8 +10805,8 @@ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "2.1.0", + "read-pkg": "3.0.0" } }, "replace-ext": { @@ -10824,7 +10821,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "semver": { @@ -10839,9 +10836,9 @@ "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" } }, "string-width": { @@ -10850,8 +10847,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "strip-ansi": { @@ -10860,7 +10857,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "strip-bom": { @@ -10875,7 +10872,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "symbol-observable": { @@ -10896,12 +10893,12 @@ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.0.2", + "replace-ext": "1.0.0" } }, "which-module": { @@ -10916,18 +10913,18 @@ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" } }, "yargs-parser": { @@ -10936,7 +10933,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" } }, "yeoman-environment": { @@ -10945,21 +10942,21 @@ "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", "dev": true, "requires": { - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "diff": "^3.3.1", - "escape-string-regexp": "^1.0.2", - "globby": "^8.0.1", - "grouped-queue": "^0.3.3", - "inquirer": "^5.2.0", - "is-scoped": "^1.0.0", - "lodash": "^4.17.10", - "log-symbols": "^2.1.0", - "mem-fs": "^1.1.0", - "strip-ansi": "^4.0.0", - "text-table": "^0.2.0", - "untildify": "^3.0.2" + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.11", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.2" } }, "yeoman-generator": { @@ -10968,31 +10965,31 @@ "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", "dev": true, "requires": { - "async": "^2.6.0", - "chalk": "^2.3.0", - "cli-table": "^0.3.1", - "cross-spawn": "^6.0.5", - "dargs": "^5.1.0", - "dateformat": "^3.0.3", - "debug": "^3.1.0", - "detect-conflict": "^1.0.0", - "error": "^7.0.2", - "find-up": "^2.1.0", - "github-username": "^4.0.0", - "istextorbinary": "^2.2.1", - "lodash": "^4.17.10", - "make-dir": "^1.1.0", - "mem-fs-editor": "^4.0.0", - "minimist": "^1.2.0", - "pretty-bytes": "^4.0.2", - "read-chunk": "^2.1.0", - "read-pkg-up": "^3.0.0", - "rimraf": "^2.6.2", - "run-async": "^2.0.0", - "shelljs": "^0.8.0", - "text-table": "^0.2.0", - "through2": "^2.0.0", - "yeoman-environment": "^2.0.5" + "async": "2.6.1", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.11", + "make-dir": "1.2.0", + "mem-fs-editor": "4.0.2", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.3.0" } } } @@ -11009,7 +11006,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-module": { @@ -11024,7 +11021,7 @@ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" } }, "window-size": { @@ -11045,8 +11042,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" } }, "wrappy": { @@ -11061,7 +11058,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.1" } }, "write-file-atomic": { @@ -11070,9 +11067,9 @@ "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" } }, "ws": { @@ -11081,9 +11078,9 @@ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" } }, "xhr": { @@ -11092,10 +11089,10 @@ "integrity": "sha1-4W5mpF+GmGHu76tBbV7/ci3ECZM=", "dev": true, "requires": { - "global": "~4.3.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" + "global": "4.3.2", + "is-function": "1.0.1", + "parse-headers": "2.0.1", + "xtend": "4.0.1" } }, "xhr-request": { @@ -11104,13 +11101,13 @@ "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", "dev": true, "requires": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" + "buffer-to-arraybuffer": "0.0.5", + "object-assign": "4.1.1", + "query-string": "5.1.1", + "simple-get": "2.8.1", + "timed-out": "4.0.1", + "url-set-query": "1.0.0", + "xhr": "2.4.0" }, "dependencies": { "simple-get": { @@ -11119,9 +11116,9 @@ "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", "dev": true, "requires": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" } } } @@ -11132,7 +11129,7 @@ "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", "dev": true, "requires": { - "xhr-request": "^1.0.1" + "xhr-request": "1.1.0" } }, "xhr2": { @@ -11172,9 +11169,9 @@ "dev": true, "optional": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" }, "dependencies": { @@ -11192,8 +11189,8 @@ "dev": true, "optional": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", + "center-align": "0.1.3", + "right-align": "0.1.3", "wordwrap": "0.0.2" } }, @@ -11219,8 +11216,8 @@ "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, "requires": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" } } } diff --git a/package.json b/package.json index 34c188877..aba5d1b80 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "eslint": "^4.19.1", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.13.0", - "eslint-plugin-mocha-no-only": "^1.0.0", + "eslint-plugin-mocha-no-only": "^1.1.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.8.0", "eslint-plugin-standard": "^3.1.0", From c0bda4db884ac026c31701a0d9aade9e7342cff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Sat, 1 Dec 2018 02:47:32 -0300 Subject: [PATCH 174/205] Updated sendTransaction, added tests. (#1528) * Renamed sendTransaction to send, improved API. * Added send tests. * Now using promisified web3 --- contracts/mocks/Acknowledger.sol | 19 +++++ test/helpers/{sendTransaction.js => send.js} | 18 ++--- test/helpers/test/balanceDifference.test.js | 6 +- test/helpers/test/send.test.js | 70 +++++++++++++++++++ test/payment/PaymentSplitter.test.js | 8 +-- test/token/ERC721/ERC721.behavior.js | 4 +- .../ERC721/ERC721PausedToken.behavior.js | 4 +- 7 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 contracts/mocks/Acknowledger.sol rename test/helpers/{sendTransaction.js => send.js} (67%) create mode 100644 test/helpers/test/send.test.js diff --git a/contracts/mocks/Acknowledger.sol b/contracts/mocks/Acknowledger.sol new file mode 100644 index 000000000..ff8f1ae04 --- /dev/null +++ b/contracts/mocks/Acknowledger.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.24; + +contract Acknowledger { + event AcknowledgeFoo(uint256 a); + event AcknowledgeBarSingle(uint256 a); + event AcknowledgeBarDouble(uint256 a, uint256 b); + + function foo(uint256 a) public { + emit AcknowledgeFoo(a); + } + + function bar(uint256 a) public { + emit AcknowledgeBarSingle(a); + } + + function bar(uint256 a, uint256 b) public { + emit AcknowledgeBarDouble(a, b); + } +} diff --git a/test/helpers/sendTransaction.js b/test/helpers/send.js similarity index 67% rename from test/helpers/sendTransaction.js rename to test/helpers/send.js index 9d4f3068f..a01fd6bcf 100644 --- a/test/helpers/sendTransaction.js +++ b/test/helpers/send.js @@ -1,4 +1,5 @@ const ethjsABI = require('ethjs-abi'); +const { ethSendTransaction } = require('./web3'); function findMethod (abi, name, args) { for (let i = 0; i < abi.length; i++) { @@ -9,22 +10,17 @@ function findMethod (abi, name, args) { } } -function sendTransaction (target, name, argsTypes, argsValues, opts) { +async function transaction (target, name, argsTypes, argsValues, opts) { const abiMethod = findMethod(target.abi, name, argsTypes); const encodedData = ethjsABI.encodeMethod(abiMethod, argsValues); return target.sendTransaction(Object.assign({ data: encodedData }, opts)); } -function sendEther (from, to, value) { - web3.eth.sendTransaction({ - from: from, - to: to, - value: value, - gasPrice: 0, - }); +function ether (from, to, value) { + return ethSendTransaction({ from, to, value, gasPrice: 0 }); } + module.exports = { - findMethod, - sendTransaction, - sendEther, + ether, + transaction, }; diff --git a/test/helpers/test/balanceDifference.test.js b/test/helpers/test/balanceDifference.test.js index e4eddc7f5..98846db9d 100644 --- a/test/helpers/test/balanceDifference.test.js +++ b/test/helpers/test/balanceDifference.test.js @@ -1,5 +1,5 @@ const { balanceDifference } = require('../balanceDifference'); -const { sendEther } = require('../sendTransaction'); +const send = require('../send'); const { ether } = require('../ether'); const BigNumber = web3.BigNumber; @@ -10,13 +10,13 @@ require('chai') contract('balanceDifference', function ([sender, receiver]) { it('returns balance increments', async function () { (await balanceDifference(receiver, () => - sendEther(sender, receiver, ether(1))) + send.ether(sender, receiver, ether(1))) ).should.be.bignumber.equal(ether(1)); }); it('returns balance decrements', async function () { (await balanceDifference(sender, () => - sendEther(sender, receiver, ether(1))) + send.ether(sender, receiver, ether(1))) ).should.be.bignumber.equal(ether(-1)); }); }); diff --git a/test/helpers/test/send.test.js b/test/helpers/test/send.test.js new file mode 100644 index 000000000..c868626a1 --- /dev/null +++ b/test/helpers/test/send.test.js @@ -0,0 +1,70 @@ +const send = require('../send'); +const shouldFail = require('../shouldFail'); +const expectEvent = require('../expectEvent'); +const { ether } = require('../ether'); +const { ethGetBalance } = require('../web3'); + +const Acknowledger = artifacts.require('Acknowledger'); + +const BigNumber = web3.BigNumber; +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +contract('send', function ([sender, receiver]) { + describe('ether', function () { + it('sends ether with no gas cost', async function () { + const value = ether(1); + + const initialSenderBalance = await ethGetBalance(sender); + const initialReceiverBalance = await ethGetBalance(receiver); + + await send.ether(sender, receiver, value); + + const finalSenderBalance = await ethGetBalance(sender); + const finalReceiverBalance = await ethGetBalance(receiver); + + finalSenderBalance.sub(initialSenderBalance).should.be.bignumber.equal(-value); + finalReceiverBalance.sub(initialReceiverBalance).should.be.bignumber.equal(value); + }); + + it('throws if the sender balance is insufficient', async function () { + const value = (await ethGetBalance(sender)).plus(1); + + await shouldFail(send.ether(sender, receiver, value)); + }); + }); + + describe('transaction', function () { + beforeEach(async function () { + this.acknowledger = await Acknowledger.new(); + }); + + it('calls a function from its signature ', async function () { + const { logs } = await send.transaction(this.acknowledger, 'foo', 'uint256', [3]); + expectEvent.inLogs(logs, 'AcknowledgeFoo', { a: 3 }); + }); + + it('calls overloaded functions with less arguments', async function () { + const { logs } = await send.transaction(this.acknowledger, 'bar', 'uint256', [3]); + expectEvent.inLogs(logs, 'AcknowledgeBarSingle', { a: 3 }); + }); + + it('calls overloaded functions with more arguments', async function () { + const { logs } = await send.transaction(this.acknowledger, 'bar', 'uint256,uint256', [3, 5]); + expectEvent.inLogs(logs, 'AcknowledgeBarDouble', { a: 3, b: 5 }); + }); + + it('throws if the number of arguments does not match', async function () { + await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256, uint256', [3, 5])); + }); + + it('throws if the method does not exist', async function () { + await shouldFail(send.transaction(this.acknowledger, 'baz', 'uint256', [3])); + }); + + it('throws if there is a mismatch in the number of types and values', async function () { + await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256', [3, 3])); + }); + }); +}); diff --git a/test/payment/PaymentSplitter.test.js b/test/payment/PaymentSplitter.test.js index 60e5654dc..34404536e 100644 --- a/test/payment/PaymentSplitter.test.js +++ b/test/payment/PaymentSplitter.test.js @@ -1,6 +1,6 @@ const { ethGetBalance } = require('../helpers/web3'); const expectEvent = require('../helpers/expectEvent'); -const { sendEther } = require('./../helpers/sendTransaction'); +const send = require('./../helpers/send'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('./../helpers/constants'); @@ -60,7 +60,7 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye }); it('should accept payments', async function () { - await sendEther(owner, this.contract.address, amount); + await send.ether(owner, this.contract.address, amount); (await ethGetBalance(this.contract.address)).should.be.bignumber.equal(amount); }); @@ -78,12 +78,12 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye }); it('should throw if non-payee want to claim', async function () { - await sendEther(payer1, this.contract.address, amount); + await send.ether(payer1, this.contract.address, amount); await shouldFail.reverting(this.contract.release(nonpayee1)); }); it('should distribute funds to payees', async function () { - await sendEther(payer1, this.contract.address, amount); + await send.ether(payer1, this.contract.address, amount); // receive funds const initBalance = await ethGetBalance(this.contract.address); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index de58710bf..d350c3f6c 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -2,7 +2,7 @@ const expectEvent = require('../../helpers/expectEvent'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const { sendTransaction } = require('../../helpers/sendTransaction'); +const send = require('../../helpers/send'); const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol'); const BigNumber = web3.BigNumber; @@ -217,7 +217,7 @@ function shouldBehaveLikeERC721 ( describe('via safeTransferFrom', function () { const safeTransferFromWithData = function (from, to, tokenId, opts) { - return sendTransaction( + return send.transaction( this.token, 'safeTransferFrom', 'address,address,uint256,bytes', diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index 1d83608fa..d44bc0565 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -1,5 +1,5 @@ const shouldFail = require('../../helpers/shouldFail'); -const { sendTransaction } = require('../../helpers/sendTransaction'); +const send = require('../../helpers/send'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const BigNumber = web3.BigNumber; @@ -36,7 +36,7 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { it('reverts when trying to safeTransferFrom with data', async function () { await shouldFail.reverting( - sendTransaction( + send.transaction( this.token, 'safeTransferFrom', 'address,address,uint256,bytes', From e7d6e863959189067c0fb57afc9f30a850d9aa9f Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Sun, 2 Dec 2018 00:09:58 -0300 Subject: [PATCH 175/205] Make Truffle provider creation lazy (#1526) * make provider creation lazy * change getter for function * remove unused networks from truffle config * remove unused dotenv package * remove truffle-hdwallet-provider dependency * install ethereumjs-util * replace sha3 with keccak256 for ethereumjs-util v6 --- .env.example | 5 - package-lock.json | 4879 +++++++++---------------- package.json | 3 +- test/cryptography/MerkleProof.test.js | 8 +- test/helpers/merkleTree.js | 8 +- truffle-config.js | 25 - 6 files changed, 1762 insertions(+), 3166 deletions(-) delete mode 100644 .env.example diff --git a/.env.example b/.env.example deleted file mode 100644 index 889306334..000000000 --- a/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -# configure your infura api key (not technically required) -INFURA_API_KEY= - -# change the mnemonic that your hd wallet is seeded with -MNEMONIC= diff --git a/package-lock.json b/package-lock.json index 53af56d9b..d3eeb9498 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { - "call-me-maybe": "1.0.1", - "glob-to-regexp": "0.3.0" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, "@nodelib/fs.stat": { @@ -26,7 +26,7 @@ "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", "dev": true, "requires": { - "any-observable": "0.3.0" + "any-observable": "^0.3.0" }, "dependencies": { "any-observable": { @@ -49,22 +49,13 @@ "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, - "abstract-leveldown": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", - "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, - "requires": { - "xtend": "4.0.1" - } - }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" }, "dependencies": { @@ -80,7 +71,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } } } @@ -97,7 +88,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -108,22 +99,16 @@ } } }, - "aes-js": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-0.2.4.tgz", - "integrity": "sha1-lLiBq3FyhtAV+iGeCPtmcJ3aWj0=", - "dev": true - }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "ajv-keywords": { @@ -138,9 +123,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" } }, "amdefine": { @@ -173,24 +158,8 @@ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } - }, - "aproba": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", - "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" } }, "argparse": { @@ -199,7 +168,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "arr-diff": { @@ -208,7 +177,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "arr-flatten": { @@ -241,7 +210,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -298,26 +267,6 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, - "async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dev": true, - "requires": { - "async": "2.6.1" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - } - } - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -354,9 +303,9 @@ "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.0", + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" } }, "babel-core": { @@ -365,25 +314,25 @@ "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.11", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" }, "dependencies": { "babel-code-frame": { @@ -392,9 +341,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-runtime": { @@ -403,8 +352,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -413,11 +362,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.11" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" } }, "babel-traverse": { @@ -426,15 +375,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.11" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" } }, "babel-types": { @@ -443,10 +392,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -484,14 +433,14 @@ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.11", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" }, "dependencies": { "babel-runtime": { @@ -500,8 +449,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -510,10 +459,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "jsesc": { @@ -536,9 +485,9 @@ "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-builder-binary-assignment-operator-visitor": { @@ -547,9 +496,9 @@ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "dev": true, "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-call-delegate": { @@ -558,10 +507,10 @@ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.25.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-define-map": { @@ -570,10 +519,10 @@ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.11" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" }, "dependencies": { "babel-runtime": { @@ -582,8 +531,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -592,10 +541,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "regenerator-runtime": { @@ -612,9 +561,9 @@ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-explode-class": { @@ -623,10 +572,10 @@ "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", "dev": true, "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.25.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-function-name": { @@ -635,11 +584,11 @@ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-get-function-arity": { @@ -648,8 +597,8 @@ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-hoist-variables": { @@ -658,8 +607,8 @@ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-optimise-call-expression": { @@ -668,8 +617,8 @@ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-regex": { @@ -678,9 +627,9 @@ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.11" + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" }, "dependencies": { "babel-runtime": { @@ -689,8 +638,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -699,10 +648,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "regenerator-runtime": { @@ -719,11 +668,11 @@ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-replace-supers": { @@ -732,12 +681,12 @@ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helpers": { @@ -746,8 +695,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-messages": { @@ -756,7 +705,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-check-es2015-constants": { @@ -765,7 +714,7 @@ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-syntax-async-functions": { @@ -840,9 +789,9 @@ "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.25.0" + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-async-to-generator": { @@ -851,9 +800,9 @@ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.25.0" + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-class-constructor-call": { @@ -862,9 +811,9 @@ "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", "dev": true, "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-class-properties": { @@ -873,10 +822,10 @@ "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-decorators": { @@ -885,11 +834,11 @@ "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", "dev": true, "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-arrow-functions": { @@ -898,7 +847,7 @@ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoped-functions": { @@ -907,7 +856,7 @@ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoping": { @@ -916,11 +865,11 @@ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.11" + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" }, "dependencies": { "babel-runtime": { @@ -929,8 +878,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -939,10 +888,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "regenerator-runtime": { @@ -959,15 +908,15 @@ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", "dev": true, "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-computed-properties": { @@ -976,8 +925,8 @@ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-destructuring": { @@ -986,7 +935,7 @@ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-duplicate-keys": { @@ -995,8 +944,8 @@ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-for-of": { @@ -1005,7 +954,7 @@ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-function-name": { @@ -1014,9 +963,9 @@ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-literals": { @@ -1025,7 +974,7 @@ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-modules-amd": { @@ -1034,9 +983,9 @@ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-commonjs": { @@ -1045,10 +994,10 @@ "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" }, "dependencies": { "babel-runtime": { @@ -1057,8 +1006,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -1067,10 +1016,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "regenerator-runtime": { @@ -1087,9 +1036,9 @@ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-umd": { @@ -1098,9 +1047,9 @@ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0" + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-object-super": { @@ -1109,8 +1058,8 @@ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "dev": true, "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.25.0" + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-parameters": { @@ -1119,12 +1068,12 @@ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", "dev": true, "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.25.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.25.0" + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-shorthand-properties": { @@ -1133,8 +1082,8 @@ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-spread": { @@ -1143,7 +1092,7 @@ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-sticky-regex": { @@ -1152,9 +1101,9 @@ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-template-literals": { @@ -1163,7 +1112,7 @@ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-typeof-symbol": { @@ -1172,7 +1121,7 @@ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "dev": true, "requires": { - "babel-runtime": "6.25.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-unicode-regex": { @@ -1181,9 +1130,9 @@ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.25.0", - "regexpu-core": "2.0.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" } }, "babel-plugin-transform-exponentiation-operator": { @@ -1192,9 +1141,9 @@ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", "dev": true, "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.25.0" + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-export-extensions": { @@ -1203,8 +1152,8 @@ "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", "dev": true, "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.25.0" + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-flow-strip-types": { @@ -1213,8 +1162,8 @@ "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "dev": true, "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.25.0" + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-object-rest-spread": { @@ -1223,8 +1172,8 @@ "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.25.0" + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-regenerator": { @@ -1242,46 +1191,8 @@ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1", - "browserslist": "3.2.8", - "invariant": "2.2.2", - "semver": "5.4.1" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-preset-es2015": { @@ -1290,30 +1201,30 @@ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1" + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-computed-properties": "^6.24.1", + "babel-plugin-transform-es2015-destructuring": "^6.22.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.22.0", + "babel-plugin-transform-es2015-function-name": "^6.24.1", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-plugin-transform-es2015-object-super": "^6.24.1", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", + "babel-plugin-transform-regenerator": "^6.24.1" } }, "babel-preset-stage-1": { @@ -1322,9 +1233,9 @@ "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", "dev": true, "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" } }, "babel-preset-stage-2": { @@ -1333,10 +1244,10 @@ "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", "dev": true, "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" } }, "babel-preset-stage-3": { @@ -1345,11 +1256,11 @@ "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", "dev": true, "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.23.0" + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.22.0" } }, "babel-register": { @@ -1358,13 +1269,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.3", - "babel-runtime": "6.26.0", - "core-js": "2.5.0", - "home-or-tmp": "2.0.0", - "lodash": "4.17.11", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" }, "dependencies": { "babel-runtime": { @@ -1373,8 +1284,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "regenerator-runtime": { @@ -1391,8 +1302,8 @@ "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.10.5" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.10.0" } }, "babel-template": { @@ -1401,11 +1312,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.11" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" }, "dependencies": { "babel-runtime": { @@ -1414,8 +1325,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -1424,10 +1335,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -1450,15 +1361,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.11" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" }, "dependencies": { "babel-code-frame": { @@ -1467,9 +1378,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-runtime": { @@ -1478,8 +1389,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.0", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -1488,10 +1399,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -1514,20 +1425,10 @@ "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "esutils": "2.0.2", - "lodash": "4.17.11", - "to-fast-properties": "1.0.3" - } - }, - "babelify": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", - "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", - "dev": true, - "requires": { - "babel-core": "6.26.3", - "object-assign": "4.1.1" + "babel-runtime": "^6.22.0", + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^1.0.1" } }, "babylon": { @@ -1536,15 +1437,6 @@ "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==", "dev": true }, - "backoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", - "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", - "dev": true, - "requires": { - "precond": "0.2.3" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -1557,13 +1449,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { @@ -1572,7 +1464,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -1581,7 +1473,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -1590,7 +1482,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -1599,9 +1491,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "isobject": { @@ -1618,12 +1510,6 @@ } } }, - "base-x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", - "integrity": "sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w=", - "dev": true - }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", @@ -1631,7 +1517,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "big.js": { @@ -1642,6 +1528,7 @@ }, "bignumber.js": { "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "from": "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", "dev": true }, "binary-extensions": { @@ -1657,40 +1544,18 @@ "dev": true }, "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", + "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==", "dev": true }, - "bip39": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", - "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", - "dev": true, - "requires": { - "create-hash": "1.1.3", - "pbkdf2": "3.0.16", - "randombytes": "2.0.6", - "safe-buffer": "5.1.1", - "unorm": "1.4.1" - } - }, "bip66": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", "dev": true, "requires": { - "safe-buffer": "5.1.1" - } - }, - "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" + "safe-buffer": "^5.0.1" } }, "bn.js": { @@ -1706,15 +1571,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", + "depd": "~1.1.2", + "http-errors": "~1.6.3", "iconv-lite": "0.4.23", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", - "type-is": "1.6.16" + "type-is": "~1.6.16" }, "dependencies": { "debug": { @@ -1732,7 +1597,7 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } }, "qs": { @@ -1749,7 +1614,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1759,9 +1624,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "brorand": { @@ -1777,16 +1642,17 @@ "dev": true }, "browserify-aes": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", - "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.0", - "inherits": "2.0.3" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-sha3": { @@ -1795,36 +1661,7 @@ "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", "dev": true, "requires": { - "js-sha3": "0.3.1" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000860", - "electron-to-chromium": "1.3.50" - } - }, - "bs58": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-3.1.0.tgz", - "integrity": "sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4=", - "dev": true, - "requires": { - "base-x": "1.1.0" - } - }, - "bs58check": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-1.3.4.tgz", - "integrity": "sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g=", - "dev": true, - "requires": { - "bs58": "3.1.0", - "create-hash": "1.1.3" + "js-sha3": "^0.3.1" } }, "buffer-from": { @@ -1863,15 +1700,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" }, "dependencies": { "isobject": { @@ -1917,7 +1754,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -1932,12 +1769,6 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "caniuse-lite": { - "version": "1.0.30000860", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000860.tgz", - "integrity": "sha512-6HCqcu+cCwWCY+WLL+rtAsAFt1ufvqMhA8dTfhMQhCJHYhJDhRRrh105DfjqRlTrDK3vvbEq8K0drNsJbymDtQ==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1951,8 +1782,8 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chai": { @@ -1961,12 +1792,12 @@ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { - "assertion-error": "1.1.0", - "check-error": "1.0.2", - "deep-eql": "3.0.1", - "get-func-name": "2.0.0", - "pathval": "1.1.0", - "type-detect": "4.0.8" + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" } }, "chai-bignumber": { @@ -1981,11 +1812,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "chardet": { @@ -2000,46 +1831,31 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, - "checkpoint-store": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", - "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", - "dev": true, - "requires": { - "functional-red-black-tree": "1.0.1" - } - }, "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.2.4", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" } }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "circular-json": { @@ -2054,10 +1870,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -2066,7 +1882,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "isobject": { @@ -2083,7 +1899,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-spinners": { @@ -2116,7 +1932,7 @@ "dev": true, "requires": { "slice-ansi": "0.0.4", - "string-width": "1.0.2" + "string-width": "^1.0.1" }, "dependencies": { "slice-ansi": { @@ -2139,9 +1955,9 @@ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "clone": { @@ -2162,7 +1978,7 @@ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "mimic-response": "1.0.0" + "mimic-response": "^1.0.0" } }, "clone-stats": { @@ -2177,9 +1993,9 @@ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.6" + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" }, "dependencies": { "process-nextick-args": { @@ -2194,13 +2010,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -2209,7 +2025,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } @@ -2226,32 +2042,14 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "coinstring": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", - "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", - "dev": true, - "requires": { - "bs58": "2.0.1", - "create-hash": "1.1.3" - }, - "dependencies": { - "bs58": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", - "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=", - "dev": true - } - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color-convert": { @@ -2260,7 +2058,7 @@ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -2281,7 +2079,7 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -2314,18 +2112,12 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "1.1.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -2386,8 +2178,8 @@ "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", "dev": true, "requires": { - "object-assign": "4.1.1", - "vary": "1.1.2" + "object-assign": "^4", + "vary": "^1" } }, "coveralls": { @@ -2396,11 +2188,11 @@ "integrity": "sha512-FAzXwiDOYLGDWH+zgoIA+8GbWv50hlx+kpEJyvzLKOdnIBv9uWoVl4DhqGgyUHpiRjAlF8KYZSipWXYtllWH6Q==", "dev": true, "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.7", - "minimist": "1.2.0", - "request": "2.87.0" + "js-yaml": "^3.6.1", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.5", + "minimist": "^1.2.0", + "request": "^2.79.0" }, "dependencies": { "minimist": { @@ -2412,39 +2204,30 @@ } }, "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.8" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, - "cross-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.1.tgz", - "integrity": "sha1-lshZEE113vyWf7XbYkdOdUJrArA=", - "dev": true, - "requires": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "cross-spawn": { @@ -2453,9 +2236,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "dependencies": { "lru-cache": { @@ -2464,8 +2247,8 @@ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } } } @@ -2488,7 +2271,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "date-fns": { @@ -2536,7 +2319,7 @@ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "mimic-response": "1.0.0" + "mimic-response": "^1.0.0" } }, "deep-eql": { @@ -2545,48 +2328,23 @@ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "4.0.8" + "type-detect": "^4.0.0" } }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "deferred-leveldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, - "requires": { - "abstract-leveldown": "2.6.3" - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.12" - } - }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -2595,7 +2353,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -2604,7 +2362,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -2613,9 +2371,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "isobject": { @@ -2632,25 +2390,19 @@ } } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.1" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "delayed-stream": { @@ -2659,12 +2411,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2689,7 +2435,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "diff": { @@ -2704,8 +2450,8 @@ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { - "arrify": "1.0.1", - "path-type": "3.0.0" + "arrify": "^1.0.1", + "path-type": "^3.0.0" }, "dependencies": { "path-type": { @@ -2714,7 +2460,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "pify": { @@ -2731,7 +2477,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "2.0.2" + "esutils": "^2.0.2" } }, "dom-walk": { @@ -2740,21 +2486,15 @@ "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", "dev": true }, - "dotenv": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", - "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", - "dev": true - }, "drbg.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", "dev": true, "requires": { - "browserify-aes": "1.0.6", - "create-hash": "1.1.3", - "create-hmac": "1.1.6" + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" } }, "duplexer3": { @@ -2770,7 +2510,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "editions": { @@ -2785,12 +2525,6 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, - "electron-to-chromium": { - "version": "1.3.50", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz", - "integrity": "sha1-dDi3b5K0G5GfP73TUPvQdX2s3fc=", - "dev": true - }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -2803,13 +2537,13 @@ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "emojis-list": { @@ -2824,33 +2558,15 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, - "requires": { - "iconv-lite": "0.4.18" - } - }, - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, "enhanced-resolve": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "tapable": "1.0.0" + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, "eol": { @@ -2865,7 +2581,7 @@ "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", "dev": true, "requires": { - "prr": "0.0.0" + "prr": "~0.0.0" }, "dependencies": { "prr": { @@ -2882,8 +2598,8 @@ "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", "dev": true, "requires": { - "string-template": "0.2.1", - "xtend": "4.0.1" + "string-template": "~0.2.1", + "xtend": "~4.0.0" } }, "error-ex": { @@ -2892,39 +2608,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" - } - }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", - "dev": true, - "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.1", - "is-callable": "1.1.3", - "is-regex": "1.0.4" - }, - "dependencies": { - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - } - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" + "is-arrayish": "^0.2.1" } }, "escape-html": { @@ -2945,11 +2629,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" }, "dependencies": { "estraverse": { @@ -2965,7 +2649,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -2976,44 +2660,44 @@ "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.22.0", - "chalk": "2.4.1", - "concat-stream": "1.6.2", - "cross-spawn": "5.1.0", - "debug": "3.1.0", - "doctrine": "2.1.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "1.0.0", - "espree": "3.5.4", - "esquery": "1.0.1", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "11.7.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.1.0", - "js-yaml": "3.12.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "regexpp": "1.1.0", - "require-uncached": "1.0.3", - "semver": "5.4.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", "table": "4.0.2", - "text-table": "0.2.0" + "text-table": "~0.2.0" }, "dependencies": { "ansi-regex": { @@ -3028,7 +2712,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "chalk": { @@ -3037,9 +2721,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "debug": { @@ -3069,8 +2753,8 @@ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "strip-ansi": { @@ -3079,7 +2763,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "supports-color": { @@ -3088,7 +2772,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -3105,8 +2789,8 @@ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { - "debug": "2.6.9", - "resolve": "1.8.1" + "debug": "^2.6.9", + "resolve": "^1.5.0" }, "dependencies": { "debug": { @@ -3124,7 +2808,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } } } @@ -3135,8 +2819,8 @@ "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", "dev": true, "requires": { - "debug": "2.6.9", - "pkg-dir": "1.0.0" + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" } }, "eslint-plugin-import": { @@ -3145,16 +2829,16 @@ "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==", "dev": true, "requires": { - "contains-path": "0.1.0", - "debug": "2.6.9", + "contains-path": "^0.1.0", + "debug": "^2.6.8", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-module-utils": "2.2.0", - "has": "1.0.1", - "lodash": "4.17.11", - "minimatch": "3.0.4", - "read-pkg-up": "2.0.0", - "resolve": "1.8.1" + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" }, "dependencies": { "doctrine": { @@ -3163,8 +2847,8 @@ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "find-up": { @@ -3173,7 +2857,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "load-json-file": { @@ -3182,10 +2866,10 @@ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" } }, "path-type": { @@ -3194,7 +2878,7 @@ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "pify": "2.3.0" + "pify": "^2.0.0" } }, "read-pkg": { @@ -3203,9 +2887,9 @@ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, "read-pkg-up": { @@ -3214,8 +2898,8 @@ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" } }, "resolve": { @@ -3224,7 +2908,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "strip-bom": { @@ -3241,7 +2925,7 @@ "integrity": "sha512-YdeWE2KpZxsRs72SFfQobvf9G5Cv25sTbely9AEdn7trstDlhcgCyWl6wH/wYf2a0tJ6At5/BOJO/+9C6QYbVQ==", "dev": true, "requires": { - "requireindex": "1.1.0" + "requireindex": "~1.1.0" } }, "eslint-plugin-node": { @@ -3250,9 +2934,9 @@ "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, "requires": { - "ignore": "3.3.7", - "minimatch": "3.0.4", - "resolve": "1.4.0", + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", "semver": "5.3.0" }, "dependencies": { @@ -3282,8 +2966,8 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint-visitor-keys": { @@ -3298,8 +2982,8 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.7.1", - "acorn-jsx": "3.0.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -3314,7 +2998,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.0.0" } }, "esrecurse": { @@ -3323,7 +3007,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.1.0" } }, "estraverse": { @@ -3344,265 +3028,19 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "eth-block-tracker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", - "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", - "dev": true, - "requires": { - "eth-query": "2.1.2", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethjs-util": "0.1.4", - "json-rpc-engine": "3.7.3", - "pify": "2.3.0", - "tape": "4.9.1" - } - }, - "eth-json-rpc-infura": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.1.2.tgz", - "integrity": "sha512-IuK5Iowfs6taluA/3Okmu6EfZcFMq6MQuyrUL1PrCoJstuuBr3TvVeSy3keDyxfbrjFB34nCo538I8G+qMtsbw==", - "dev": true, - "requires": { - "cross-fetch": "2.2.1", - "eth-json-rpc-middleware": "1.6.0", - "json-rpc-engine": "3.7.3", - "json-rpc-error": "2.0.0", - "tape": "4.9.1" - } - }, - "eth-json-rpc-middleware": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", - "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", - "dev": true, - "requires": { - "async": "2.6.1", - "eth-query": "2.1.2", - "eth-tx-summary": "3.2.3", - "ethereumjs-block": "1.7.1", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethereumjs-vm": "2.3.5", - "fetch-ponyfill": "4.1.0", - "json-rpc-engine": "3.7.3", - "json-rpc-error": "2.0.0", - "json-stable-stringify": "1.0.1", - "promise-to-callback": "1.0.0", - "tape": "4.9.1" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - } - } - }, "eth-lib": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0", - "keccakjs": "0.2.1", - "nano-json-stream-parser": "0.1.2", - "servify": "0.1.12", - "ws": "3.3.3", - "xhr-request-promise": "0.1.2" - } - }, - "eth-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", - "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", - "dev": true, - "requires": { - "json-rpc-random-id": "1.0.1", - "xtend": "4.0.1" - } - }, - "eth-sig-util": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", - "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", - "dev": true, - "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "ethereumjs-util": "5.2.0" - }, - "dependencies": { - "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "ethereumjs-util": "5.2.0" - } - } - } - }, - "eth-tx-summary": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.3.tgz", - "integrity": "sha512-1gZpA5fKarJOVSb5OUlPnhDQuIazqAkI61zlVvf5LdG47nEgw+/qhyZnuj3CUdE/TLTKuRzPLeyXLjaB4qWTRQ==", - "dev": true, - "requires": { - "async": "2.6.1", - "bn.js": "4.11.8", - "clone": "2.1.1", - "concat-stream": "1.6.2", - "end-of-stream": "1.4.0", - "eth-query": "2.1.2", - "ethereumjs-block": "1.7.1", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethereumjs-vm": "2.3.4", - "through2": "2.0.3", - "treeify": "1.1.0", - "web3-provider-engine": "13.8.0" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - }, - "eth-block-tracker": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz", - "integrity": "sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA==", - "dev": true, - "requires": { - "async-eventemitter": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "eth-query": "2.1.2", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethjs-util": "0.1.4", - "json-rpc-engine": "3.7.3", - "pify": "2.3.0", - "tape": "4.9.1" - }, - "dependencies": { - "async-eventemitter": { - "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "dev": true, - "requires": { - "async": "2.6.1" - } - } - } - }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - }, - "ethereumjs-vm": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz", - "integrity": "sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw==", - "dev": true, - "requires": { - "async": "2.6.1", - "async-eventemitter": "0.2.4", - "ethereum-common": "0.2.0", - "ethereumjs-account": "2.0.5", - "ethereumjs-block": "1.7.1", - "ethereumjs-util": "5.2.0", - "fake-merkle-patricia-tree": "1.0.1", - "functional-red-black-tree": "1.0.1", - "merkle-patricia-tree": "2.3.1", - "rustbn.js": "0.1.2", - "safe-buffer": "5.1.1" - } - }, - "web3-provider-engine": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz", - "integrity": "sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ==", - "dev": true, - "requires": { - "async": "2.6.1", - "clone": "2.1.1", - "eth-block-tracker": "2.3.1", - "eth-sig-util": "1.4.2", - "ethereumjs-block": "1.7.1", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethereumjs-vm": "2.3.4", - "fetch-ponyfill": "4.1.0", - "json-rpc-error": "2.0.0", - "json-stable-stringify": "1.0.1", - "promise-to-callback": "1.0.0", - "readable-stream": "2.3.3", - "request": "2.87.0", - "semaphore": "1.1.0", - "solc": "0.4.24", - "tape": "4.9.1", - "xhr": "2.4.0", - "xtend": "4.0.1" - } - } - } - }, - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true - }, - "ethereumjs-account": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", - "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "dev": true, - "requires": { - "ethereumjs-util": "5.2.0", - "rlp": "2.0.0", - "safe-buffer": "5.1.1" - } - }, - "ethereumjs-block": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", - "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "dev": true, - "requires": { - "async": "2.6.1", - "ethereum-common": "0.2.0", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "merkle-patricia-tree": "2.3.1" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - } + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "keccakjs": "^0.2.1", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" } }, "ethereumjs-testrpc-sc": { @@ -3611,8 +3049,8 @@ "integrity": "sha512-dBTav4AZQ7zuajmICv1k7bEesqS+8f0u0wciXNUJZb842RTBi0lgKEDF8WgZshzv4ThI+XVQSRNV/A+seiK4aA==", "dev": true, "requires": { - "source-map-support": "0.5.6", - "webpack-cli": "2.1.5" + "source-map-support": "^0.5.3", + "webpack-cli": "^2.0.9" }, "dependencies": { "source-map": { @@ -3627,107 +3065,25 @@ "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", "dev": true, "requires": { - "buffer-from": "1.1.0", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } } } }, - "ethereumjs-tx": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.5.tgz", - "integrity": "sha512-cPr0BxitCaffq0qQwZRHJgiNCM/3IIJqkYbweeUCyPwV77S+GlQHou2L3afKEFtfiAjfaa82T9LnSmY/pM8iYQ==", - "dev": true, - "requires": { - "ethereum-common": "0.0.18", - "ethereumjs-util": "5.2.0" - } - }, "ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.0.0.tgz", + "integrity": "sha512-E3yKUyl0Fs95nvTFQZe/ZSNcofhDzUsDlA5y2uoRmf1+Ec7gpGhNCsgKkZBRh7Br5op8mJcYF/jFbmjj909+nQ==", "dev": true, "requires": { - "bn.js": "4.11.8", - "create-hash": "1.1.3", - "ethjs-util": "0.1.4", - "keccak": "1.3.0", - "rlp": "2.0.0", - "safe-buffer": "5.1.1", - "secp256k1": "3.3.0" - } - }, - "ethereumjs-vm": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.5.tgz", - "integrity": "sha512-AJ7x44+xqyE5+UO3Nns19WkTdZfyqFZ+sEjIEpvme7Ipbe3iBU1uwCcHEdiu/yY9bdhr3IfSa/NfIKNeXPaRVQ==", - "dev": true, - "requires": { - "async": "2.6.1", - "async-eventemitter": "0.2.4", - "ethereum-common": "0.2.0", - "ethereumjs-account": "2.0.5", - "ethereumjs-block": "1.7.1", - "ethereumjs-util": "5.2.0", - "fake-merkle-patricia-tree": "1.0.1", - "functional-red-black-tree": "1.0.1", - "merkle-patricia-tree": "2.3.1", - "rustbn.js": "0.1.2", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - }, - "ethereum-common": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true - } - } - }, - "ethereumjs-wallet": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz", - "integrity": "sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s=", - "dev": true, - "requires": { - "aes-js": "0.2.4", - "bs58check": "1.3.4", - "ethereumjs-util": "4.5.0", - "hdkey": "0.7.1", - "scrypt.js": "0.2.0", - "utf8": "2.1.2", - "uuid": "2.0.3" - }, - "dependencies": { - "ethereumjs-util": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", - "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "create-hash": "1.1.3", - "keccakjs": "0.2.1", - "rlp": "2.0.0", - "secp256k1": "3.3.0" - } - }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" } }, "ethjs-abi": { @@ -3774,9 +3130,9 @@ } }, "ethjs-util": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.4.tgz", - "integrity": "sha1-HItoeSV0RO9NPz+7rC3tEs2ZfZM=", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", "dev": true, "requires": { "is-hex-prefixed": "1.0.0", @@ -3784,12 +3140,13 @@ } }, "evp_bytestokey": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", - "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { - "create-hash": "1.1.3" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "execa": { @@ -3798,13 +3155,13 @@ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, "exit-hook": { @@ -3819,7 +3176,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "expand-range": { @@ -3828,22 +3185,16 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.4" + "fill-range": "^2.1.0" } }, - "expand-template": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.0.3.tgz", - "integrity": "sha1-bDAzIxd6YrGyLAcCefeGEoe2mxo=", - "dev": true - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } }, "express": { @@ -3852,36 +3203,36 @@ "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", + "proxy-addr": "~2.0.3", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", + "statuses": "~1.4.0", + "type-is": "~1.6.16", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "body-parser": { @@ -3891,15 +3242,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.3", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.16" + "type-is": "~1.6.15" } }, "debug": { @@ -3950,7 +3301,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "statuses": ">= 1.3.1 < 2" } }, "setprototypeof": { @@ -3981,8 +3332,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -3991,7 +3342,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -4002,9 +3353,9 @@ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", "dev": true, "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.18", - "tmp": "0.0.33" + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" } }, "extglob": { @@ -4013,7 +3364,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "extsprintf": { @@ -4022,15 +3373,6 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, - "fake-merkle-patricia-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", - "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", - "dev": true, - "requires": { - "checkpoint-store": "1.1.0" - } - }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", @@ -4043,12 +3385,12 @@ "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", "dev": true, "requires": { - "@mrmlnc/readdir-enhanced": "2.2.1", - "@nodelib/fs.stat": "1.1.0", - "glob-parent": "3.1.0", - "is-glob": "4.0.0", - "merge2": "1.2.2", - "micromatch": "3.1.10" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.0.1", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.1", + "micromatch": "^3.1.10" }, "dependencies": { "arr-diff": { @@ -4069,16 +3411,16 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -4087,7 +3429,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4098,13 +3440,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -4113,7 +3455,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -4122,7 +3464,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -4131,7 +3473,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4140,7 +3482,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } } } @@ -4151,7 +3493,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4160,7 +3502,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } } } @@ -4171,9 +3513,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "kind-of": { @@ -4190,14 +3532,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -4206,7 +3548,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -4215,7 +3557,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4226,10 +3568,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -4238,7 +3580,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -4249,8 +3591,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { @@ -4259,7 +3601,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } } } @@ -4270,7 +3612,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -4279,7 +3621,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -4288,9 +3630,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "is-extglob": { @@ -4305,7 +3647,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.1" } }, "is-number": { @@ -4314,7 +3656,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -4323,7 +3665,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } } } @@ -4346,19 +3688,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.13", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } } } @@ -4375,34 +3717,13 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fetch-ponyfill": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", - "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", - "dev": true, - "requires": { - "node-fetch": "1.7.3" - }, - "dependencies": { - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - } - } - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -4411,8 +3732,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "filename-regex": { @@ -4427,11 +3748,11 @@ "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "3.0.0", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" }, "dependencies": { "kind-of": { @@ -4446,9 +3767,9 @@ "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, "requires": { - "is-number": "4.0.0", - "kind-of": "6.0.2", - "math-random": "1.0.1" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" }, "dependencies": { "is-number": { @@ -4468,12 +3789,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -4499,8 +3820,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "first-chunk-stream": { @@ -4509,7 +3830,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "^2.0.2" } }, "flat-cache": { @@ -4518,10 +3839,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" } }, "flow-parser": { @@ -4536,7 +3857,7 @@ "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", "dev": true, "requires": { - "is-function": "1.0.1" + "is-function": "~1.0.0" } }, "for-in": { @@ -4551,15 +3872,9 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -4572,9 +3887,9 @@ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "forwarded": { @@ -4589,7 +3904,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { @@ -4604,8 +3919,8 @@ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, "fs-extra": { @@ -4614,11 +3929,11 @@ "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1", - "path-is-absolute": "1.0.1", - "rimraf": "2.6.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" } }, "fs.realpath": { @@ -4634,8 +3949,8 @@ "dev": true, "optional": true, "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.10.0" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { "abbrev": { @@ -4661,8 +3976,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "balanced-match": { @@ -4675,7 +3990,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -4739,7 +4054,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.2.4" + "minipass": "^2.2.1" } }, "fs.realpath": { @@ -4754,14 +4069,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "glob": { @@ -4770,12 +4085,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-unicode": { @@ -4790,7 +4105,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "^2.1.0" } }, "ignore-walk": { @@ -4799,7 +4114,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "inflight": { @@ -4808,8 +4123,8 @@ "dev": true, "optional": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -4828,7 +4143,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -4842,7 +4157,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -4855,8 +4170,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" } }, "minizlib": { @@ -4865,7 +4180,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "2.2.4" + "minipass": "^2.2.1" } }, "mkdirp": { @@ -4888,9 +4203,9 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, "node-pre-gyp": { @@ -4899,16 +4214,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, "nopt": { @@ -4917,8 +4232,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npm-bundled": { @@ -4933,8 +4248,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { @@ -4943,10 +4258,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -4965,7 +4280,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -4986,8 +4301,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -5008,10 +4323,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -5028,13 +4343,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "rimraf": { @@ -5043,7 +4358,7 @@ "dev": true, "optional": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -5086,9 +4401,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -5097,7 +4412,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -5105,7 +4420,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -5120,13 +4435,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" } }, "util-deprecate": { @@ -5141,7 +4456,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -5174,8 +4489,8 @@ "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", "dev": true, "requires": { - "source-map-support": "0.5.4", - "webpack-cli": "2.1.5" + "source-map-support": "^0.5.3", + "webpack-cli": "^2.0.9" }, "dependencies": { "source-map": { @@ -5190,27 +4505,11 @@ "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", "dev": true, "requires": { - "source-map": "0.6.1" + "source-map": "^0.6.0" } } } }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "1.1.2", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -5241,7 +4540,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "gh-got": { @@ -5250,8 +4549,8 @@ "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", "dev": true, "requires": { - "got": "7.1.0", - "is-plain-obj": "1.1.0" + "got": "^7.0.0", + "is-plain-obj": "^1.1.0" }, "dependencies": { "got": { @@ -5260,20 +4559,20 @@ "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", "dev": true, "requires": { - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-plain-obj": "1.1.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.1", - "p-cancelable": "0.3.0", - "p-timeout": "1.2.1", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "1.0.0", - "url-to-options": "1.0.1" + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" } }, "p-cancelable": { @@ -5288,7 +4587,7 @@ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", "dev": true, "requires": { - "p-finally": "1.0.0" + "p-finally": "^1.0.0" } }, "prepend-http": { @@ -5303,24 +4602,18 @@ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { - "prepend-http": "1.0.4" + "prepend-http": "^1.0.1" } } } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, "github-username": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", "dev": true, "requires": { - "gh-got": "6.0.0" + "gh-got": "^6.0.0" } }, "glob": { @@ -5329,12 +4622,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-all": { @@ -5343,8 +4636,8 @@ "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", "dev": true, "requires": { - "glob": "7.1.2", - "yargs": "1.2.6" + "glob": "^7.0.5", + "yargs": "~1.2.6" }, "dependencies": { "minimist": { @@ -5359,7 +4652,7 @@ "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", "dev": true, "requires": { - "minimist": "0.1.0" + "minimist": "^0.1.0" } } } @@ -5370,8 +4663,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" } }, "glob-parent": { @@ -5380,7 +4673,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "glob-to-regexp": { @@ -5395,8 +4688,8 @@ "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", "dev": true, "requires": { - "min-document": "2.19.0", - "process": "0.5.2" + "min-document": "^2.19.0", + "process": "~0.5.1" } }, "global-modules": { @@ -5405,9 +4698,9 @@ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" } }, "global-prefix": { @@ -5416,11 +4709,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "1.0.2", - "which": "1.3.0" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" } }, "globals": { @@ -5435,12 +4728,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "graceful-fs": { @@ -5455,7 +4748,7 @@ "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", "dev": true, "requires": { - "lodash": "4.17.11" + "lodash": "^4.17.2" } }, "growl": { @@ -5470,10 +4763,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "source-map": { @@ -5482,7 +4775,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -5499,8 +4792,8 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, "has": { @@ -5509,7 +4802,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "1.1.0" + "function-bind": "^1.0.2" } }, "has-ansi": { @@ -5518,7 +4811,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-color": { @@ -5545,24 +4838,18 @@ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "requires": { - "has-symbol-support-x": "1.4.2" + "has-symbol-support-x": "^1.4.1" } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" }, "dependencies": { "isobject": { @@ -5579,8 +4866,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "is-number": { @@ -5589,7 +4876,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -5598,7 +4885,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } } } @@ -5609,18 +4896,19 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } } } }, "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "hash.js": { @@ -5629,18 +4917,8 @@ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hdkey": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", - "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", - "dev": true, - "requires": { - "coinstring": "2.3.0", - "secp256k1": "3.3.0" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" } }, "he": { @@ -5655,9 +4933,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "home-or-tmp": { @@ -5666,8 +4944,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "homedir-polyfill": { @@ -5676,7 +4954,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { @@ -5697,10 +4975,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.5.0" + "statuses": ">= 1.4.0 < 2" } }, "http-signature": { @@ -5709,9 +4987,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "iconv-lite": { @@ -5726,20 +5004,14 @@ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, "import-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" }, "dependencies": { "find-up": { @@ -5748,7 +5020,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "pkg-dir": { @@ -5757,7 +5029,7 @@ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "2.1.0" + "find-up": "^2.1.0" } } } @@ -5774,7 +5046,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "inflight": { @@ -5783,8 +5055,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -5805,20 +5077,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.11", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" }, "dependencies": { "ansi-regex": { @@ -5833,7 +5105,7 @@ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "chalk": { @@ -5842,9 +5114,9 @@ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" } }, "has-flag": { @@ -5865,8 +5137,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -5875,7 +5147,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "supports-color": { @@ -5884,7 +5156,7 @@ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -5901,8 +5173,8 @@ "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "dev": true, "requires": { - "from2": "2.3.0", - "p-is-promise": "1.1.0" + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" } }, "invariant": { @@ -5911,7 +5183,7 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "invert-kv": { @@ -5932,7 +5204,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "is-arrayish": { @@ -5947,7 +5219,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -5962,39 +5234,27 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { @@ -6017,7 +5277,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -6038,22 +5298,16 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, - "is-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", - "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-function": { @@ -6068,7 +5322,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "is-hex-prefixed": { @@ -6083,7 +5337,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "is-object": { @@ -6104,7 +5358,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -6113,7 +5367,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-plain-obj": { @@ -6128,7 +5382,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" }, "dependencies": { "isobject": { @@ -6157,15 +5411,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "1.0.1" - } - }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -6184,7 +5429,7 @@ "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", "dev": true, "requires": { - "scoped-regex": "1.0.0" + "scoped-regex": "^1.0.0" } }, "is-stream": { @@ -6193,12 +5438,6 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -6256,20 +5495,20 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.6.1", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "glob": { @@ -6278,11 +5517,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-flag": { @@ -6303,7 +5542,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -6314,9 +5553,9 @@ "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", "dev": true, "requires": { - "binaryextensions": "2.1.1", - "editions": "1.3.4", - "textextensions": "2.2.0" + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" } }, "isurl": { @@ -6325,8 +5564,8 @@ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "requires": { - "has-to-string-tag-x": "1.4.1", - "is-object": "1.0.1" + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" } }, "js-sha3": { @@ -6353,8 +5592,8 @@ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" + "argparse": "^1.0.7", + "esprima": "^2.6.0" } }, "jsbn": { @@ -6370,21 +5609,21 @@ "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", "dev": true, "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-1": "6.24.1", - "babel-register": "6.26.0", - "babylon": "7.0.0-beta.47", - "colors": "1.1.2", - "flow-parser": "0.69.0", - "lodash": "4.17.11", - "micromatch": "2.3.11", - "neo-async": "2.5.0", + "babel-plugin-transform-flow-strip-types": "^6.8.0", + "babel-preset-es2015": "^6.9.0", + "babel-preset-stage-1": "^6.5.0", + "babel-register": "^6.9.0", + "babylon": "^7.0.0-beta.47", + "colors": "^1.1.2", + "flow-parser": "^0.*", + "lodash": "^4.13.1", + "micromatch": "^2.3.7", + "neo-async": "^2.5.0", "node-dir": "0.1.8", - "nomnom": "1.8.1", - "recast": "0.15.0", - "temp": "0.8.3", - "write-file-atomic": "1.3.4" + "nomnom": "^1.8.1", + "recast": "^0.15.0", + "temp": "^0.8.1", + "write-file-atomic": "^1.2.0" }, "dependencies": { "ast-types": { @@ -6412,9 +5651,9 @@ "dev": true, "requires": { "ast-types": "0.11.5", - "esprima": "4.0.0", - "private": "0.1.7", - "source-map": "0.6.1" + "esprima": "~4.0.0", + "private": "~0.1.5", + "source-map": "~0.6.1" } }, "source-map": { @@ -6443,46 +5682,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-rpc-engine": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.7.3.tgz", - "integrity": "sha512-+FO3UWu/wafh/+MZ6BXy0HZU+f5plwUn82FgxpC0scJkEh5snOjFrAAtqCITPDfvfLHRUFOG5pQDUx2pspfERQ==", - "dev": true, - "requires": { - "async": "2.6.1", - "babel-preset-env": "1.7.0", - "babelify": "7.3.0", - "clone": "2.1.1", - "json-rpc-error": "2.0.0", - "promise-to-callback": "1.0.0" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - } - } - }, - "json-rpc-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", - "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "json-rpc-random-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", - "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=", - "dev": true - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -6495,15 +5694,6 @@ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -6528,15 +5718,9 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6550,16 +5734,15 @@ } }, "keccak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.3.0.tgz", - "integrity": "sha512-JgsKPxYhcJxKrV+TrCyg/GwZbOjhpRPrz2kG8xbAsUaIDelUlKjm08YcwBO9Fm8sqf/Kg8ZWkk6nWujhLykfvw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", "dev": true, "requires": { - "bindings": "1.3.0", - "inherits": "2.0.3", - "nan": "2.10.0", - "prebuild-install": "2.2.2", - "safe-buffer": "5.1.1" + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" } }, "keccakjs": { @@ -6568,8 +5751,8 @@ "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", "dev": true, "requires": { - "browserify-sha3": "0.0.1", - "sha3": "1.2.2" + "browserify-sha3": "^0.0.1", + "sha3": "^1.1.0" } }, "keyv": { @@ -6587,7 +5770,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "^1.1.5" } }, "klaw": { @@ -6596,7 +5779,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.9" } }, "lazy-cache": { @@ -6612,7 +5795,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "lcov-parse": { @@ -6621,133 +5804,14 @@ "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, - "level-codec": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true - }, - "level-errors": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", - "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, - "requires": { - "errno": "0.1.4" - } - }, - "level-iterator-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", - "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "level-errors": "1.0.5", - "readable-stream": "1.1.14", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "level-ws": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", - "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "2.1.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "0.4.0" - } - } - } - }, - "levelup": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, - "requires": { - "deferred-leveldown": "1.2.2", - "level-codec": "7.0.1", - "level-errors": "1.0.5", - "level-iterator-stream": "1.3.1", - "prr": "1.0.1", - "semver": "5.4.1", - "xtend": "4.0.1" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "listr-silent-renderer": { @@ -6762,14 +5826,14 @@ "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-truncate": "0.2.1", - "elegant-spinner": "1.0.1", - "figures": "1.7.0", - "indent-string": "3.2.0", - "log-symbols": "1.0.2", - "log-update": "1.0.2", - "strip-ansi": "3.0.1" + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^1.0.2", + "strip-ansi": "^3.0.1" }, "dependencies": { "figures": { @@ -6778,8 +5842,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "indent-string": { @@ -6794,7 +5858,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.0.0" } } } @@ -6805,10 +5869,10 @@ "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "date-fns": "1.29.0", - "figures": "1.7.0" + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" }, "dependencies": { "cli-cursor": { @@ -6817,7 +5881,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "figures": { @@ -6826,8 +5890,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "onetime": { @@ -6842,8 +5906,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } } } @@ -6854,11 +5918,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, "loader-utils": { @@ -6867,9 +5931,9 @@ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "3.1.3", - "emojis-list": "2.1.0", - "json5": "0.5.1" + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" } }, "locate-path": { @@ -6878,8 +5942,8 @@ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "dependencies": { "path-exists": { @@ -6914,7 +5978,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "2.3.2" + "chalk": "^2.0.1" }, "dependencies": { "ansi-styles": { @@ -6923,7 +5987,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "chalk": { @@ -6932,9 +5996,9 @@ "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.3.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "has-flag": { @@ -6949,7 +6013,7 @@ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -6960,8 +6024,8 @@ "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "cli-cursor": "1.0.2" + "ansi-escapes": "^1.0.0", + "cli-cursor": "^1.0.2" }, "dependencies": { "ansi-escapes": { @@ -6976,7 +6040,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "onetime": { @@ -6991,8 +6055,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } } } @@ -7009,7 +6073,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0" } }, "lowercase-keys": { @@ -7018,19 +6082,13 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" }, "dependencies": { "pify": { @@ -7053,7 +6111,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "math-random": { @@ -7062,6 +6120,25 @@ "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", "dev": true }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -7074,7 +6151,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "^1.0.0" } }, "mem-fs": { @@ -7083,34 +6160,9 @@ "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", "dev": true, "requires": { - "through2": "2.0.3", - "vinyl": "1.2.0", - "vinyl-file": "2.0.0" - } - }, - "memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "requires": { - "abstract-leveldown": "2.7.2", - "functional-red-black-tree": "1.0.1", - "immediate": "3.2.3", - "inherits": "2.0.3", - "ltgt": "2.2.1", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "requires": { - "xtend": "4.0.1" - } - } + "through2": "^2.0.0", + "vinyl": "^1.1.0", + "vinyl-file": "^2.0.0" } }, "memory-fs": { @@ -7119,8 +6171,8 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.4", - "readable-stream": "2.3.3" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, "memorystream": { @@ -7141,22 +6193,6 @@ "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==", "dev": true }, - "merkle-patricia-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", - "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", - "dev": true, - "requires": { - "async": "1.5.2", - "ethereumjs-util": "5.2.0", - "level-ws": "0.0.0", - "levelup": "1.3.9", - "memdown": "1.4.1", - "readable-stream": "2.3.3", - "rlp": "2.0.0", - "semaphore": "1.1.0" - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -7169,19 +6205,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } }, "mime": { @@ -7202,7 +6238,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mimic-fn": { @@ -7223,7 +6259,7 @@ "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", "dev": true, "requires": { - "dom-walk": "0.1.1" + "dom-walk": "^0.1.0" } }, "minimalistic-assert": { @@ -7244,7 +6280,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -7259,8 +6295,8 @@ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -7269,7 +6305,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -7322,7 +6358,7 @@ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -7339,10 +6375,10 @@ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" } }, "mute-stream": { @@ -7369,17 +6405,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "arr-diff": { @@ -7426,32 +6462,20 @@ "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", "dev": true }, - "node-abi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.1.0.tgz", - "integrity": "sha512-AbW35CPRE4vdieOse46V+16dKispLNv3PQwgqlcfg7GQeQHcLu3gvp3fbU2gTh7d8NfGjp5CJh+j4Hpyb0XzaA==", - "dev": true - }, "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=", "dev": true }, - "node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true - }, "nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", "dev": true, "requires": { - "chalk": "0.4.0", - "underscore": "1.6.0" + "chalk": "~0.4.0", + "underscore": "~1.6.0" }, "dependencies": { "ansi-styles": { @@ -7466,9 +6490,9 @@ "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { - "ansi-styles": "1.0.0", - "has-color": "0.1.7", - "strip-ansi": "0.1.1" + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" } }, "strip-ansi": { @@ -7479,19 +6503,13 @@ } } }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.9" + "abbrev": "1" } }, "normalize-package-data": { @@ -7500,10 +6518,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -7512,7 +6530,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.0.2" + "remove-trailing-separator": "^1.0.1" } }, "normalize-url": { @@ -7521,9 +6539,9 @@ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", "dev": true, "requires": { - "prepend-http": "2.0.0", - "query-string": "5.1.1", - "sort-keys": "2.0.0" + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" } }, "npm-run-path": { @@ -7532,19 +6550,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "path-key": "^2.0.0" } }, "number-is-nan": { @@ -7589,9 +6595,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -7600,30 +6606,18 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } }, - "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", - "dev": true - }, - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true - }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" }, "dependencies": { "isobject": { @@ -7640,8 +6634,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" } }, "object.pick": { @@ -7650,7 +6644,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" }, "dependencies": { "isobject": { @@ -7676,7 +6670,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -7685,7 +6679,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "^1.0.0" } }, "optimist": { @@ -7694,8 +6688,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { "wordwrap": { @@ -7712,12 +6706,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, "ora": { @@ -7726,10 +6720,10 @@ "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", "dev": true, "requires": { - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-spinners": "0.1.2", - "object-assign": "4.1.1" + "chalk": "^1.1.1", + "cli-cursor": "^1.0.2", + "cli-spinners": "^0.1.2", + "object-assign": "^4.0.1" }, "dependencies": { "cli-cursor": { @@ -7738,7 +6732,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "onetime": { @@ -7753,8 +6747,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } } } @@ -7777,7 +6771,7 @@ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "1.0.0" + "lcid": "^1.0.0" } }, "os-tmpdir": { @@ -7798,7 +6792,7 @@ "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "requires": { - "p-reduce": "1.0.0" + "p-reduce": "^1.0.0" } }, "p-finally": { @@ -7831,7 +6825,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.1.0" + "p-limit": "^1.1.0" } }, "p-map": { @@ -7852,7 +6846,7 @@ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", "dev": true, "requires": { - "p-finally": "1.0.0" + "p-finally": "^1.0.0" } }, "parse-glob": { @@ -7861,10 +6855,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" } }, "parse-headers": { @@ -7873,7 +6867,7 @@ "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", "dev": true, "requires": { - "for-each": "0.3.2", + "for-each": "^0.3.2", "trim": "0.0.1" } }, @@ -7883,7 +6877,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "parse-passwd": { @@ -7916,7 +6910,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } }, "path-is-absolute": { @@ -7955,9 +6949,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "pathval": { @@ -7966,19 +6960,6 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, - "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, "pegjs": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", @@ -8009,7 +6990,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pkg-dir": { @@ -8018,7 +6999,7 @@ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "^1.0.0" } }, "pluralize": { @@ -8033,51 +7014,6 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "prebuild-install": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.2.2.tgz", - "integrity": "sha512-F46pcvDxtQhbV3B+dm+exHuKxIyJK26fVNiJRmbTW/5D7o0Z2yzc8CKeu7UWbo9XxQZoVOC88aKgySAsza+cWw==", - "dev": true, - "requires": { - "expand-template": "1.0.3", - "github-from-package": "0.0.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "node-abi": "2.1.0", - "noop-logger": "0.1.1", - "npmlog": "4.1.2", - "os-homedir": "1.0.2", - "pump": "1.0.2", - "rc": "1.2.8", - "simple-get": "1.4.3", - "tar-fs": "1.15.3", - "tunnel-agent": "0.6.0", - "xtend": "4.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "precond": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=", - "dev": true - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -8126,48 +7062,22 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, - "promise-to-callback": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", - "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", - "dev": true, - "requires": { - "is-fn": "1.0.0", - "set-immediate-shim": "1.0.1" - } - }, "proxy-addr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "dev": true, "requires": { - "forwarded": "0.1.2", + "forwarded": "~0.1.2", "ipaddr.js": "1.6.0" } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, - "pump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", - "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", - "dev": true, - "requires": { - "end-of-stream": "1.4.0", - "once": "1.4.0" - } - }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -8186,18 +7096,9 @@ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { - "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, "randomhex": { @@ -8230,45 +7131,19 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } } } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "0.6.0", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", "dev": true, "requires": { - "pify": "3.0.0", - "safe-buffer": "5.1.1" + "pify": "^3.0.0", + "safe-buffer": "^5.1.1" }, "dependencies": { "pify": { @@ -8285,9 +7160,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" } }, "read-pkg-up": { @@ -8296,8 +7171,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, "readable-stream": { @@ -8306,13 +7181,13 @@ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "readdirp": { @@ -8321,10 +7196,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.3", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" } }, "rechoir": { @@ -8333,7 +7208,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.4.0" + "resolve": "^1.1.6" } }, "regenerate": { @@ -8354,9 +7229,9 @@ "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0", - "private": "0.1.7" + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" } }, "regex-cache": { @@ -8365,8 +7240,8 @@ "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" + "is-equal-shallow": "^0.1.3", + "is-primitive": "^2.0.0" } }, "regex-not": { @@ -8375,8 +7250,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "regexpp": { @@ -8391,9 +7266,9 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } }, "regjsgen": { @@ -8408,7 +7283,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" } }, "remove-trailing-separator": { @@ -8435,7 +7310,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "replace-ext": { @@ -8450,7 +7325,7 @@ "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", "dev": true, "requires": { - "req-from": "1.0.1" + "req-from": "^1.0.1" } }, "req-from": { @@ -8459,7 +7334,7 @@ "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", "dev": true, "requires": { - "resolve-from": "2.0.0" + "resolve-from": "^2.0.0" }, "dependencies": { "resolve-from": { @@ -8476,26 +7351,26 @@ "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "dev": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.7.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.1", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.3.0" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "require-directory": { @@ -8522,8 +7397,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, "requireindex": { @@ -8538,7 +7413,7 @@ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-cwd": { @@ -8547,7 +7422,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "3.0.0" + "resolve-from": "^3.0.0" }, "dependencies": { "resolve-from": { @@ -8564,8 +7439,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } }, "resolve-from": { @@ -8586,7 +7461,7 @@ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "dev": true, "requires": { - "lowercase-keys": "1.0.1" + "lowercase-keys": "^1.0.0" } }, "restore-cursor": { @@ -8595,17 +7470,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "resumer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", - "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", - "dev": true, - "requires": { - "through": "2.3.8" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "ret": { @@ -8621,7 +7487,7 @@ "dev": true, "optional": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -8630,24 +7496,27 @@ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "rlp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", - "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", + "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } }, "run-async": { "version": "2.3.0", @@ -8655,15 +7524,9 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "^2.1.0" } }, - "rustbn.js": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.1.2.tgz", - "integrity": "sha512-bAkNqSHYdJdFsBC7Z11JgzYktL31HIpB2o70jZcGiL1U1TVtPyvaVhDrGWwS8uZtaqwW2k6NOPGZCqW/Dgh5Lg==", - "dev": true - }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -8676,7 +7539,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "4.0.8" + "rx-lite": "*" } }, "rxjs": { @@ -8700,7 +7563,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, "safer-buffer": { @@ -8715,57 +7578,22 @@ "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", "dev": true }, - "scrypt": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", - "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", - "dev": true, - "requires": { - "nan": "2.10.0" - } - }, - "scrypt.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", - "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", - "dev": true, - "requires": { - "scrypt": "6.0.3", - "scryptsy": "1.2.1" - } - }, - "scryptsy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", - "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", - "dev": true, - "requires": { - "pbkdf2": "3.0.16" - } - }, "secp256k1": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.3.0.tgz", - "integrity": "sha512-CbrQoeGG5V0kQ1ohEMGI+J7oKerapLTpivLICBaXR0R4HyQcN3kM9itLsV5fdpV1UR1bD14tOkJ1xughmlDIiQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz", + "integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==", "dev": true, "requires": { - "bindings": "1.3.0", - "bip66": "1.1.5", - "bn.js": "4.11.8", - "create-hash": "1.1.3", - "drbg.js": "1.0.1", - "elliptic": "6.4.0", - "nan": "2.10.0", - "prebuild-install": "2.2.2", - "safe-buffer": "5.1.1" + "bindings": "^1.2.1", + "bip66": "^1.1.3", + "bn.js": "^4.11.3", + "create-hash": "^1.1.2", + "drbg.js": "^1.0.1", + "elliptic": "^6.2.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" } }, - "semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", - "dev": true - }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", @@ -8779,18 +7607,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.3", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { "debug": { @@ -8816,9 +7644,9 @@ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.2" } }, @@ -8828,11 +7656,11 @@ "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", "dev": true, "requires": { - "body-parser": "1.18.3", - "cors": "2.8.4", - "express": "4.16.3", - "request": "2.87.0", - "xhr": "2.4.0" + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" } }, "set-blocking": { @@ -8853,10 +7681,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -8865,7 +7693,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -8877,12 +7705,13 @@ "dev": true }, "sha.js": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", - "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "sha3": { @@ -8900,7 +7729,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -8915,9 +7744,9 @@ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.0.3", - "rechoir": "0.6.2" + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } }, "signal-exit": { @@ -8932,17 +7761,6 @@ "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", "dev": true }, - "simple-get": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz", - "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", - "dev": true, - "requires": { - "once": "1.4.0", - "unzip-response": "1.0.2", - "xtend": "4.0.1" - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -8955,7 +7773,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0" + "is-fullwidth-code-point": "^2.0.0" }, "dependencies": { "is-fullwidth-code-point": { @@ -8978,14 +7796,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.2", - "use": "3.1.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "define-property": { @@ -8994,7 +7812,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -9003,7 +7821,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -9014,9 +7832,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -9025,7 +7843,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { @@ -9034,7 +7852,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-data-descriptor": { @@ -9043,7 +7861,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-descriptor": { @@ -9052,9 +7870,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "isobject": { @@ -9077,7 +7895,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" } }, "sol-digger": { @@ -9098,11 +7916,11 @@ "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", "dev": true, "requires": { - "fs-extra": "0.30.0", - "memorystream": "0.3.1", - "require-from-string": "1.2.1", - "semver": "5.4.1", - "yargs": "4.8.1" + "fs-extra": "^0.30.0", + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "semver": "^5.3.0", + "yargs": "^4.7.1" }, "dependencies": { "yargs": { @@ -9111,20 +7929,20 @@ "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" } } } @@ -9135,16 +7953,16 @@ "integrity": "sha512-UvjLBgUJiLvufU6K9xmf/gPIU7DhWcDmBA6iTJ0dZI7LsvU+vugN1/ByZojU54kWLpaODx0A+P4cIT0jcRVNNw==", "dev": true, "requires": { - "death": "1.1.0", + "death": "^1.1.0", "ethereumjs-testrpc-sc": "6.1.2", - "istanbul": "0.4.5", - "keccakjs": "0.2.1", - "req-cwd": "1.0.1", - "shelljs": "0.7.8", - "sol-explore": "1.6.2", + "istanbul": "^0.4.5", + "keccakjs": "^0.2.1", + "req-cwd": "^1.0.1", + "shelljs": "^0.7.4", + "sol-explore": "^1.6.2", "solidity-parser-sc": "0.4.10", - "tree-kill": "1.2.0", - "web3": "0.18.4" + "tree-kill": "^1.2.0", + "web3": "^0.18.4" } }, "solidity-parser-sc": { @@ -9153,9 +7971,9 @@ "integrity": "sha512-oGgFpeX4OzvOfku/Bnw3/yrOmcVJTgXa994HjZwWXA/kHVZ4L1ml9BcbWHRAziJYm3ObHCXlKumfMCBXBt9K8Q==", "dev": true, "requires": { - "mocha": "4.1.0", - "pegjs": "0.10.0", - "yargs": "4.8.1" + "mocha": "^4.1.0", + "pegjs": "^0.10.0", + "yargs": "^4.6.0" }, "dependencies": { "yargs": { @@ -9164,20 +7982,20 @@ "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "dev": true, "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" } } } @@ -9188,18 +8006,18 @@ "integrity": "sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA==", "dev": true, "requires": { - "ajv": "5.5.2", - "chokidar": "1.7.0", - "colors": "1.1.2", - "commander": "2.11.0", - "eol": "0.9.1", - "js-string-escape": "1.0.1", - "lodash": "4.17.11", + "ajv": "^5.2.2", + "chokidar": "^1.6.0", + "colors": "^1.1.2", + "commander": "^2.9.0", + "eol": "^0.9.1", + "js-string-escape": "^1.0.1", + "lodash": "^4.14.2", "sol-digger": "0.0.2", "sol-explore": "1.6.1", "solium-plugin-security": "0.1.1", "solparse": "2.2.5", - "text-table": "0.2.0" + "text-table": "^0.2.0" }, "dependencies": { "ansi-regex": { @@ -9220,9 +8038,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, "find-up": { @@ -9231,7 +8049,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "is-fullwidth-code-point": { @@ -9246,9 +8064,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "sol-explore": { @@ -9263,9 +8081,9 @@ "integrity": "sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA==", "dev": true, "requires": { - "mocha": "4.1.0", - "pegjs": "0.10.0", - "yargs": "10.1.2" + "mocha": "^4.0.1", + "pegjs": "^0.10.0", + "yargs": "^10.0.3" } }, "string-width": { @@ -9274,8 +8092,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -9284,7 +8102,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "which-module": { @@ -9299,18 +8117,18 @@ "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", "dev": true, "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "8.1.0" + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" } }, "yargs-parser": { @@ -9319,7 +8137,7 @@ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -9336,7 +8154,7 @@ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } }, "source-map": { @@ -9351,11 +8169,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "2.1.1", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { @@ -9364,7 +8182,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" } }, "source-map-url": { @@ -9379,7 +8197,7 @@ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-license-ids": "^1.0.2" } }, "spdx-expression-parse": { @@ -9400,7 +8218,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -9415,15 +8233,15 @@ "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "static-extend": { @@ -9432,8 +8250,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -9442,7 +8260,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } } } @@ -9471,20 +8289,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0", - "function-bind": "1.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -9493,7 +8300,7 @@ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -9502,7 +8309,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -9511,7 +8318,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } }, "strip-bom-stream": { @@ -9520,8 +8327,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "2.0.0", - "strip-bom": "2.0.0" + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" } }, "strip-eof": { @@ -9563,12 +8370,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.5.2", - "ajv-keywords": "2.1.1", - "chalk": "2.4.1", - "lodash": "4.17.11", + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", "slice-ansi": "1.0.0", - "string-width": "2.1.1" + "string-width": "^2.1.1" }, "dependencies": { "ansi-regex": { @@ -9583,7 +8390,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "chalk": { @@ -9592,9 +8399,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "is-fullwidth-code-point": { @@ -9609,8 +8416,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -9619,7 +8426,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "supports-color": { @@ -9628,7 +8435,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } } } @@ -9639,100 +8446,14 @@ "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true }, - "tape": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", - "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", - "dev": true, - "requires": { - "deep-equal": "1.0.1", - "defined": "1.0.0", - "for-each": "0.3.3", - "function-bind": "1.1.1", - "glob": "7.1.2", - "has": "1.0.3", - "inherits": "2.0.3", - "minimist": "1.2.0", - "object-inspect": "1.6.0", - "resolve": "1.7.1", - "resumer": "0.0.0", - "string.prototype.trim": "1.1.2", - "through": "2.3.8" - }, - "dependencies": { - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "1.1.3" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "1.1.1" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - } - } - }, - "tar-fs": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.15.3.tgz", - "integrity": "sha1-7M+TXpQUk9gVECjmNuUc5MPKfyA=", - "dev": true, - "requires": { - "chownr": "1.0.1", - "mkdirp": "0.5.1", - "pump": "1.0.2", - "tar-stream": "1.5.4" - } - }, - "tar-stream": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", - "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", - "dev": true, - "requires": { - "bl": "1.2.1", - "end-of-stream": "1.4.0", - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "dev": true, "requires": { - "os-tmpdir": "1.0.2", - "rimraf": "2.2.8" + "os-tmpdir": "^1.0.0", + "rimraf": "~2.2.6" }, "dependencies": { "rimraf": { @@ -9767,8 +8488,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } }, "timed-out": { @@ -9783,7 +8504,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "to-fast-properties": { @@ -9798,7 +8519,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "to-regex": { @@ -9807,10 +8528,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -9819,8 +8540,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" }, "dependencies": { "is-number": { @@ -9829,7 +8550,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } } } @@ -9840,7 +8561,7 @@ "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "tree-kill": { @@ -9849,12 +8570,6 @@ "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", "dev": true }, - "treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", - "dev": true - }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -9873,23 +8588,11 @@ "integrity": "sha1-vydYaYi0/4RWPt+/MrR5QUCKdq0=", "dev": true, "requires": { - "mocha": "4.1.0", + "mocha": "^4.1.0", "original-require": "1.0.1", "solc": "0.4.24" } }, - "truffle-hdwallet-provider": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.5.tgz", - "integrity": "sha512-dVVcHIOy7DRwVs+BeDt39pvHnHak1zb1BQ30pHaux7fmxk/T/TJVKp18D584qCWnCbnSt8bMdB3XxALPLXIbVw==", - "dev": true, - "requires": { - "bip39": "2.5.0", - "ethereumjs-wallet": "0.6.0", - "web3": "0.18.4", - "web3-provider-engine": "14.0.6" - } - }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -9902,7 +8605,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -9918,7 +8621,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-detect": { @@ -9934,7 +8637,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" }, "dependencies": { "mime-db": { @@ -9949,7 +8652,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } } } @@ -9967,9 +8670,9 @@ "dev": true, "optional": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" } }, "uglify-to-browserify": { @@ -9997,10 +8700,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -10009,7 +8712,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -10018,20 +8721,14 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } }, - "unorm": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", - "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=", - "dev": true - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -10044,8 +8741,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -10054,9 +8751,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -10090,12 +8787,6 @@ "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", "dev": true }, - "unzip-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", - "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", - "dev": true - }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -10108,7 +8799,7 @@ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, "requires": { - "prepend-http": "2.0.0" + "prepend-http": "^2.0.0" } }, "url-set-query": { @@ -10129,7 +8820,7 @@ "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.2" }, "dependencies": { "kind-of": { @@ -10170,8 +8861,8 @@ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" } }, "vary": { @@ -10186,9 +8877,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "vinyl": { @@ -10197,8 +8888,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" }, "dependencies": { @@ -10216,12 +8907,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0", - "strip-bom-stream": "2.0.0", - "vinyl": "1.2.0" + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" } }, "web3": { @@ -10231,59 +8922,10 @@ "dev": true, "requires": { "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "3.1.8", - "utf8": "2.1.2", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - }, - "web3-provider-engine": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.0.6.tgz", - "integrity": "sha512-tr5cGSyxfSC/JqiUpBlJtfZpwQf1yAA8L/zy1C6fDFm0ntR974pobJ4v4676atpZne4Ze5VFy3kPPahHe9gQiQ==", - "dev": true, - "requires": { - "async": "2.6.1", - "backoff": "2.5.0", - "clone": "2.1.1", - "cross-fetch": "2.2.1", - "eth-block-tracker": "3.0.1", - "eth-json-rpc-infura": "3.1.2", - "eth-sig-util": "1.4.2", - "ethereumjs-block": "1.7.1", - "ethereumjs-tx": "1.3.5", - "ethereumjs-util": "5.2.0", - "ethereumjs-vm": "2.3.5", - "json-rpc-error": "2.0.0", - "json-stable-stringify": "1.0.1", - "promise-to-callback": "1.0.0", - "readable-stream": "2.3.3", - "request": "2.87.0", - "semaphore": "1.1.0", - "tape": "4.9.1", - "ws": "5.2.1", - "xhr": "2.4.0", - "xtend": "4.0.1" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "4.17.11" - } - }, - "ws": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.1.tgz", - "integrity": "sha512-2NkHdPKjDBj3CHdnAGNpmlliryKqF+n9MYXX7/wsVC4yqYocKreKNjydPDvT3wShAZnndlM0RytEfTALCDvz7A==", - "dev": true, - "requires": { - "async-limiter": "1.0.0" - } - } + "crypto-js": "^3.1.4", + "utf8": "^2.1.1", + "xhr2": "*", + "xmlhttprequest": "*" } }, "web3-utils": { @@ -10327,7 +8969,7 @@ "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", "dev": true, "requires": { - "jscodeshift": "0.4.1" + "jscodeshift": "^0.4.0" }, "dependencies": { "ast-types": { @@ -10348,21 +8990,21 @@ "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", "dev": true, "requires": { - "async": "1.5.2", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-1": "6.24.1", - "babel-register": "6.26.0", - "babylon": "6.17.4", - "colors": "1.1.2", - "flow-parser": "0.69.0", - "lodash": "4.17.11", - "micromatch": "2.3.11", + "async": "^1.5.0", + "babel-plugin-transform-flow-strip-types": "^6.8.0", + "babel-preset-es2015": "^6.9.0", + "babel-preset-stage-1": "^6.5.0", + "babel-register": "^6.9.0", + "babylon": "^6.17.3", + "colors": "^1.1.2", + "flow-parser": "^0.*", + "lodash": "^4.13.1", + "micromatch": "^2.3.7", "node-dir": "0.1.8", - "nomnom": "1.8.1", - "recast": "0.12.9", - "temp": "0.8.3", - "write-file-atomic": "1.3.4" + "nomnom": "^1.8.1", + "recast": "^0.12.5", + "temp": "^0.8.1", + "write-file-atomic": "^1.2.0" } }, "recast": { @@ -10372,10 +9014,10 @@ "dev": true, "requires": { "ast-types": "0.10.1", - "core-js": "2.5.0", - "esprima": "4.0.0", - "private": "0.1.7", - "source-map": "0.6.1" + "core-js": "^2.4.1", + "esprima": "~4.0.0", + "private": "~0.1.5", + "source-map": "~0.6.1" } }, "source-map": { @@ -10392,32 +9034,32 @@ "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", "dev": true, "requires": { - "chalk": "2.4.1", - "cross-spawn": "6.0.5", - "diff": "3.5.0", - "enhanced-resolve": "4.1.0", - "envinfo": "5.10.0", - "glob-all": "3.1.0", - "global-modules": "1.0.0", - "got": "8.3.1", - "import-local": "1.0.0", - "inquirer": "5.2.0", - "interpret": "1.1.0", - "jscodeshift": "0.5.1", - "listr": "0.14.1", - "loader-utils": "1.1.0", - "lodash": "4.17.11", - "log-symbols": "2.2.0", - "mkdirp": "0.5.1", - "p-each-series": "1.0.0", - "p-lazy": "1.0.0", - "prettier": "1.13.6", - "supports-color": "5.4.0", - "v8-compile-cache": "2.0.0", - "webpack-addons": "1.1.5", - "yargs": "11.1.0", - "yeoman-environment": "2.3.0", - "yeoman-generator": "2.0.5" + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "diff": "^3.5.0", + "enhanced-resolve": "^4.0.0", + "envinfo": "^5.7.0", + "glob-all": "^3.1.0", + "global-modules": "^1.0.0", + "got": "^8.3.1", + "import-local": "^1.0.0", + "inquirer": "^5.2.0", + "interpret": "^1.1.0", + "jscodeshift": "^0.5.0", + "listr": "^0.14.1", + "loader-utils": "^1.1.0", + "lodash": "^4.17.10", + "log-symbols": "^2.2.0", + "mkdirp": "^0.5.1", + "p-each-series": "^1.0.0", + "p-lazy": "^1.0.0", + "prettier": "^1.12.1", + "supports-color": "^5.4.0", + "v8-compile-cache": "^2.0.0", + "webpack-addons": "^1.1.5", + "yargs": "^11.1.0", + "yeoman-environment": "^2.1.1", + "yeoman-generator": "^2.0.5" }, "dependencies": { "ansi-regex": { @@ -10432,7 +9074,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "async": { @@ -10441,7 +9083,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "4.17.11" + "lodash": "^4.17.10" } }, "camelcase": { @@ -10456,9 +9098,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "cliui": { @@ -10467,9 +9109,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, "clone-stats": { @@ -10484,11 +9126,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", - "shebang-command": "1.2.0", - "which": "1.3.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "debug": { @@ -10530,7 +9172,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "globby": { @@ -10539,13 +9181,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "1.0.2", - "dir-glob": "2.0.0", - "fast-glob": "2.2.2", - "glob": "7.1.2", - "ignore": "3.3.7", - "pify": "3.0.0", - "slash": "1.0.0" + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" } }, "got": { @@ -10554,23 +9196,23 @@ "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", "dev": true, "requires": { - "@sindresorhus/is": "0.7.0", - "cacheable-request": "2.1.4", - "decompress-response": "3.3.0", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "into-stream": "3.1.0", - "is-retry-allowed": "1.1.0", - "isurl": "1.0.0", - "lowercase-keys": "1.0.1", - "mimic-response": "1.0.0", - "p-cancelable": "0.4.1", - "p-timeout": "2.0.1", - "pify": "3.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "url-parse-lax": "3.0.0", - "url-to-options": "1.0.1" + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" } }, "inquirer": { @@ -10579,19 +9221,19 @@ "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.4.1", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.11", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rxjs": "5.5.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" } }, "interpret": { @@ -10612,7 +9254,7 @@ "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dev": true, "requires": { - "symbol-observable": "1.2.0" + "symbol-observable": "^1.1.0" } }, "listr": { @@ -10621,22 +9263,22 @@ "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", "dev": true, "requires": { - "@samverschueren/stream-to-observable": "0.3.0", - "cli-truncate": "0.2.1", - "figures": "1.7.0", - "indent-string": "2.1.0", - "is-observable": "1.1.0", - "is-promise": "2.1.0", - "is-stream": "1.1.0", - "listr-silent-renderer": "1.1.1", - "listr-update-renderer": "0.4.0", - "listr-verbose-renderer": "0.4.1", - "log-symbols": "1.0.2", - "log-update": "1.0.2", - "ora": "0.2.3", - "p-map": "1.2.0", - "rxjs": "6.2.1", - "strip-ansi": "3.0.1" + "@samverschueren/stream-to-observable": "^0.3.0", + "cli-truncate": "^0.2.1", + "figures": "^1.7.0", + "indent-string": "^2.1.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.4.0", + "listr-verbose-renderer": "^0.4.0", + "log-symbols": "^1.0.2", + "log-update": "^1.0.2", + "ora": "^0.2.3", + "p-map": "^1.1.1", + "rxjs": "^6.1.0", + "strip-ansi": "^3.0.1" }, "dependencies": { "ansi-regex": { @@ -10657,11 +9299,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "figures": { @@ -10670,8 +9312,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "log-symbols": { @@ -10680,7 +9322,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.0.0" } }, "rxjs": { @@ -10689,7 +9331,7 @@ "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", "dev": true, "requires": { - "tslib": "1.9.3" + "tslib": "^1.9.0" } }, "strip-ansi": { @@ -10698,7 +9340,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "supports-color": { @@ -10715,10 +9357,10 @@ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" } }, "mem-fs-editor": { @@ -10727,17 +9369,17 @@ "integrity": "sha512-QHvdXLLNmwJXxKdf7x27aNUren6IoPxwcM8Sfd+S6/ddQQMcYdEtVKsh6ilpqMrU18VQuKZEaH0aCGt3JDbA0g==", "dev": true, "requires": { - "commondir": "1.0.1", - "deep-extend": "0.5.1", - "ejs": "2.6.1", - "glob": "7.1.2", - "globby": "8.0.1", - "isbinaryfile": "3.0.2", - "mkdirp": "0.5.1", - "multimatch": "2.1.0", - "rimraf": "2.6.2", - "through2": "2.0.3", - "vinyl": "2.2.0" + "commondir": "^1.0.1", + "deep-extend": "^0.5.1", + "ejs": "^2.5.9", + "glob": "^7.0.3", + "globby": "^8.0.0", + "isbinaryfile": "^3.0.2", + "mkdirp": "^0.5.0", + "multimatch": "^2.0.0", + "rimraf": "^2.2.8", + "through2": "^2.0.0", + "vinyl": "^2.0.1" } }, "minimist": { @@ -10752,9 +9394,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "parse-json": { @@ -10763,8 +9405,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.2" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "path-type": { @@ -10773,7 +9415,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "pify": { @@ -10794,9 +9436,9 @@ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "4.0.0", - "normalize-package-data": "2.4.0", - "path-type": "3.0.0" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" } }, "read-pkg-up": { @@ -10805,8 +9447,8 @@ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "3.0.0" + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" } }, "replace-ext": { @@ -10821,7 +9463,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "semver": { @@ -10836,9 +9478,9 @@ "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } }, "string-width": { @@ -10847,8 +9489,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -10857,7 +9499,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "strip-bom": { @@ -10872,7 +9514,7 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "3.0.0" + "has-flag": "^3.0.0" } }, "symbol-observable": { @@ -10893,12 +9535,12 @@ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.0.2", - "replace-ext": "1.0.0" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "which-module": { @@ -10913,18 +9555,18 @@ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" } }, "yargs-parser": { @@ -10933,7 +9575,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } }, "yeoman-environment": { @@ -10942,21 +9584,21 @@ "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", "dev": true, "requires": { - "chalk": "2.4.1", - "cross-spawn": "6.0.5", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "globby": "8.0.1", - "grouped-queue": "0.3.3", - "inquirer": "5.2.0", - "is-scoped": "1.0.0", - "lodash": "4.17.11", - "log-symbols": "2.2.0", - "mem-fs": "1.1.3", - "strip-ansi": "4.0.0", - "text-table": "0.2.0", - "untildify": "3.0.2" + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "diff": "^3.3.1", + "escape-string-regexp": "^1.0.2", + "globby": "^8.0.1", + "grouped-queue": "^0.3.3", + "inquirer": "^5.2.0", + "is-scoped": "^1.0.0", + "lodash": "^4.17.10", + "log-symbols": "^2.1.0", + "mem-fs": "^1.1.0", + "strip-ansi": "^4.0.0", + "text-table": "^0.2.0", + "untildify": "^3.0.2" } }, "yeoman-generator": { @@ -10965,48 +9607,42 @@ "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", "dev": true, "requires": { - "async": "2.6.1", - "chalk": "2.4.1", - "cli-table": "0.3.1", - "cross-spawn": "6.0.5", - "dargs": "5.1.0", - "dateformat": "3.0.3", - "debug": "3.1.0", - "detect-conflict": "1.0.1", - "error": "7.0.2", - "find-up": "2.1.0", - "github-username": "4.1.0", - "istextorbinary": "2.2.1", - "lodash": "4.17.11", - "make-dir": "1.2.0", - "mem-fs-editor": "4.0.2", - "minimist": "1.2.0", - "pretty-bytes": "4.0.2", - "read-chunk": "2.1.0", - "read-pkg-up": "3.0.0", - "rimraf": "2.6.2", - "run-async": "2.3.0", - "shelljs": "0.8.2", - "text-table": "0.2.0", - "through2": "2.0.3", - "yeoman-environment": "2.3.0" + "async": "^2.6.0", + "chalk": "^2.3.0", + "cli-table": "^0.3.1", + "cross-spawn": "^6.0.5", + "dargs": "^5.1.0", + "dateformat": "^3.0.3", + "debug": "^3.1.0", + "detect-conflict": "^1.0.0", + "error": "^7.0.2", + "find-up": "^2.1.0", + "github-username": "^4.0.0", + "istextorbinary": "^2.2.1", + "lodash": "^4.17.10", + "make-dir": "^1.1.0", + "mem-fs-editor": "^4.0.0", + "minimist": "^1.2.0", + "pretty-bytes": "^4.0.2", + "read-chunk": "^2.1.0", + "read-pkg-up": "^3.0.0", + "rimraf": "^2.6.2", + "run-async": "^2.0.0", + "shelljs": "^0.8.0", + "text-table": "^0.2.0", + "through2": "^2.0.0", + "yeoman-environment": "^2.0.5" } } } }, - "whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", - "dev": true - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { @@ -11015,15 +9651,6 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "dev": true, - "requires": { - "string-width": "1.0.2" - } - }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", @@ -11042,8 +9669,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" } }, "wrappy": { @@ -11058,7 +9685,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "write-file-atomic": { @@ -11067,9 +9694,9 @@ "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" } }, "ws": { @@ -11078,9 +9705,9 @@ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, "xhr": { @@ -11089,10 +9716,10 @@ "integrity": "sha1-4W5mpF+GmGHu76tBbV7/ci3ECZM=", "dev": true, "requires": { - "global": "4.3.2", - "is-function": "1.0.1", - "parse-headers": "2.0.1", - "xtend": "4.0.1" + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" } }, "xhr-request": { @@ -11101,13 +9728,13 @@ "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", "dev": true, "requires": { - "buffer-to-arraybuffer": "0.0.5", - "object-assign": "4.1.1", - "query-string": "5.1.1", - "simple-get": "2.8.1", - "timed-out": "4.0.1", - "url-set-query": "1.0.0", - "xhr": "2.4.0" + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" }, "dependencies": { "simple-get": { @@ -11116,9 +9743,9 @@ "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", "dev": true, "requires": { - "decompress-response": "3.3.0", - "once": "1.4.0", - "simple-concat": "1.0.0" + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } } } @@ -11129,7 +9756,7 @@ "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", "dev": true, "requires": { - "xhr-request": "1.1.0" + "xhr-request": "^1.0.1" } }, "xhr2": { @@ -11169,9 +9796,9 @@ "dev": true, "optional": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" }, "dependencies": { @@ -11189,8 +9816,8 @@ "dev": true, "optional": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, @@ -11216,8 +9843,8 @@ "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" } } } diff --git a/package.json b/package.json index aba5d1b80..0320514b3 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "chai": "^4.1.2", "chai-bignumber": "^2.0.2", "coveralls": "^3.0.1", - "dotenv": "^4.0.0", "eslint": "^4.19.1", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.13.0", @@ -49,12 +48,12 @@ "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.8.0", "eslint-plugin-standard": "^3.1.0", + "ethereumjs-util": "^6.0.0", "ethjs-abi": "^0.2.1", "ganache-cli": "6.1.0", "solidity-coverage": "^0.5.4", "solium": "^1.1.8", "truffle": "^4.1.13", - "truffle-hdwallet-provider": "0.0.5", "web3-utils": "^1.0.0-beta.34" }, "dependencies": {} diff --git a/test/cryptography/MerkleProof.test.js b/test/cryptography/MerkleProof.test.js index b5d8fbe07..8940b240c 100644 --- a/test/cryptography/MerkleProof.test.js +++ b/test/cryptography/MerkleProof.test.js @@ -1,5 +1,5 @@ const { MerkleTree } = require('../helpers/merkleTree.js'); -const { sha3, bufferToHex } = require('ethereumjs-util'); +const { keccak256, bufferToHex } = require('ethereumjs-util'); const MerkleProofWrapper = artifacts.require('MerkleProofWrapper'); @@ -20,7 +20,7 @@ contract('MerkleProof', function () { const proof = merkleTree.getHexProof(elements[0]); - const leaf = bufferToHex(sha3(elements[0])); + const leaf = bufferToHex(keccak256(elements[0])); (await this.merkleProof.verify(proof, root, leaf)).should.equal(true); }); @@ -31,7 +31,7 @@ contract('MerkleProof', function () { const correctRoot = correctMerkleTree.getHexRoot(); - const correctLeaf = bufferToHex(sha3(correctElements[0])); + const correctLeaf = bufferToHex(keccak256(correctElements[0])); const badElements = ['d', 'e', 'f']; const badMerkleTree = new MerkleTree(badElements); @@ -50,7 +50,7 @@ contract('MerkleProof', function () { const proof = merkleTree.getHexProof(elements[0]); const badProof = proof.slice(0, proof.length - 5); - const leaf = bufferToHex(sha3(elements[0])); + const leaf = bufferToHex(keccak256(elements[0])); (await this.merkleProof.verify(badProof, root, leaf)).should.equal(false); }); diff --git a/test/helpers/merkleTree.js b/test/helpers/merkleTree.js index 8afa32511..27a8b201d 100644 --- a/test/helpers/merkleTree.js +++ b/test/helpers/merkleTree.js @@ -1,9 +1,9 @@ -const { sha3, bufferToHex } = require('ethereumjs-util'); +const { keccak256, bufferToHex } = require('ethereumjs-util'); class MerkleTree { constructor (elements) { // Filter empty strings and hash elements - this.elements = elements.filter(el => el).map(el => sha3(el)); + this.elements = elements.filter(el => el).map(el => keccak256(el)); // Deduplicate elements this.elements = this.bufDedup(this.elements); @@ -45,7 +45,7 @@ class MerkleTree { if (!first) { return second; } if (!second) { return first; } - return sha3(this.sortAndConcat(first, second)); + return keccak256(this.sortAndConcat(first, second)); } getRoot () { @@ -97,7 +97,7 @@ class MerkleTree { // Convert element to 32 byte hash if it is not one already if (el.length !== 32 || !Buffer.isBuffer(el)) { - hash = sha3(el); + hash = keccak256(el); } else { hash = el; } diff --git a/truffle-config.js b/truffle-config.js index 52708daa9..eab1846c7 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -1,19 +1,3 @@ -require('dotenv').config(); - -const HDWalletProvider = require('truffle-hdwallet-provider'); - -const providerWithMnemonic = (mnemonic, rpcEndpoint) => - new HDWalletProvider(mnemonic, rpcEndpoint); - -const infuraProvider = network => providerWithMnemonic( - process.env.MNEMONIC || '', - `https://${network}.infura.io/${process.env.INFURA_API_KEY}` -); - -const ropstenProvider = process.env.SOLIDITY_COVERAGE - ? undefined - : infuraProvider('ropsten'); - module.exports = { networks: { development: { @@ -21,10 +5,6 @@ module.exports = { port: 8545, network_id: '*', // eslint-disable-line camelcase }, - ropsten: { - provider: ropstenProvider, - network_id: 3, // eslint-disable-line camelcase - }, coverage: { host: 'localhost', network_id: '*', // eslint-disable-line camelcase @@ -32,10 +12,5 @@ module.exports = { gas: 0xfffffffffff, gasPrice: 0x01, }, - ganache: { - host: 'localhost', - port: 8545, - network_id: '*', // eslint-disable-line camelcase - }, }, }; From 41c540fb1e80f92cd67dfe165b16e2eaaacbb9bc Mon Sep 17 00:00:00 2001 From: Remon Nashid Date: Mon, 3 Dec 2018 16:07:37 -0500 Subject: [PATCH 176/205] Update to ganache-cli@6.1.8 (#1535) --- package-lock.json | 44 +++++++++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3eeb9498..fd2f2ac70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3983,12 +3983,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4003,17 +4005,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4130,7 +4135,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4142,6 +4148,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4156,6 +4163,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4163,12 +4171,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4187,6 +4197,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4267,7 +4278,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4279,6 +4291,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4400,6 +4413,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4484,13 +4498,12 @@ "dev": true }, "ganache-cli": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.0.tgz", - "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.8.tgz", + "integrity": "sha512-yXzteu4SIgUL31mnpm9j+x6dpHUw0p/nsRVkcySKq0w+1vDxH9jMErP1QhZAJuTVE6ni4nfvGSNkaQx5cD3jfg==", "dev": true, "requires": { - "source-map-support": "^0.5.3", - "webpack-cli": "^2.0.9" + "source-map-support": "^0.5.3" }, "dependencies": { "source-map": { @@ -4500,11 +4513,12 @@ "dev": true }, "source-map-support": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", - "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "dev": true, "requires": { + "buffer-from": "^1.0.0", "source-map": "^0.6.0" } } diff --git a/package.json b/package.json index 0320514b3..2c65ee66b 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "eslint-plugin-standard": "^3.1.0", "ethereumjs-util": "^6.0.0", "ethjs-abi": "^0.2.1", - "ganache-cli": "6.1.0", + "ganache-cli": "6.1.8", "solidity-coverage": "^0.5.4", "solium": "^1.1.8", "truffle": "^4.1.13", From b7d56d54714e01ad023429712eedb496361186bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Mon, 3 Dec 2018 19:15:30 -0300 Subject: [PATCH 177/205] Added explicity pify dep, deprecating web3.eth. (#1532) * Added explicity pify dep, deprecating web3.eth. * Dropped promisify in favor of pify. --- package-lock.json | 62 +++++++++++++++++++++++++++++-- package.json | 1 + test/helpers/balanceDifference.js | 6 ++- test/helpers/expectEvent.js | 3 +- test/helpers/time.js | 6 +-- test/helpers/web3.js | 3 +- 6 files changed, 71 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd2f2ac70..b5ce5da27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2403,6 +2403,14 @@ "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "rimraf": "^2.2.8" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "delayed-stream": { @@ -2870,6 +2878,14 @@ "parse-json": "^2.2.0", "pify": "^2.0.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "path-type": { @@ -2879,6 +2895,14 @@ "dev": true, "requires": { "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "read-pkg": { @@ -4748,6 +4772,14 @@ "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "graceful-fs": { @@ -5937,6 +5969,14 @@ "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "strip-bom": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "loader-utils": { @@ -6966,6 +7006,14 @@ "graceful-fs": "^4.1.2", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "pathval": { @@ -6987,9 +7035,9 @@ "dev": true }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, "pinkie": { @@ -8927,6 +8975,14 @@ "strip-bom": "^2.0.0", "strip-bom-stream": "^2.0.0", "vinyl": "^1.1.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "web3": { diff --git a/package.json b/package.json index 2c65ee66b..fa030dfc5 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "ethereumjs-util": "^6.0.0", "ethjs-abi": "^0.2.1", "ganache-cli": "6.1.8", + "pify": "^4.0.1", "solidity-coverage": "^0.5.4", "solium": "^1.1.8", "truffle": "^4.1.13", diff --git a/test/helpers/balanceDifference.js b/test/helpers/balanceDifference.js index 883d7df49..e514b0160 100644 --- a/test/helpers/balanceDifference.js +++ b/test/helpers/balanceDifference.js @@ -1,7 +1,9 @@ +const { ethGetBalance } = require('./web3'); + async function balanceDifference (account, promiseFunc) { - const balanceBefore = web3.eth.getBalance(account); + const balanceBefore = await ethGetBalance(account); await promiseFunc(); - const balanceAfter = web3.eth.getBalance(account); + const balanceAfter = await ethGetBalance(account); return balanceAfter.minus(balanceBefore); } diff --git a/test/helpers/expectEvent.js b/test/helpers/expectEvent.js index 690a09979..3cb6b37ec 100644 --- a/test/helpers/expectEvent.js +++ b/test/helpers/expectEvent.js @@ -1,4 +1,5 @@ const SolidityEvent = require('web3/lib/web3/event.js'); +const { ethGetTransactionReceipt } = require('./web3'); const BigNumber = web3.BigNumber; const should = require('chai') @@ -23,7 +24,7 @@ async function inConstruction (contract, eventName, eventArgs = {}) { } async function inTransaction (txHash, emitter, eventName, eventArgs = {}) { - const receipt = await web3.eth.getTransactionReceipt(txHash); + const receipt = await ethGetTransactionReceipt(txHash); const logs = decodeLogs(receipt.logs, emitter.events); return inLogs(logs, eventName, eventArgs); diff --git a/test/helpers/time.js b/test/helpers/time.js index 727250831..c8c844079 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -1,8 +1,8 @@ const { ethGetBlock } = require('./web3'); -const { promisify } = require('util'); +const pify = require('pify'); function advanceBlock () { - return promisify(web3.currentProvider.sendAsync)({ + return pify(web3.currentProvider.sendAsync)({ jsonrpc: '2.0', method: 'evm_mine', }); @@ -18,7 +18,7 @@ async function latest () { async function increase (duration) { if (duration < 0) throw Error(`Cannot increase time by a negative amount (${duration})`); - await promisify(web3.currentProvider.sendAsync)({ + await pify(web3.currentProvider.sendAsync)({ jsonrpc: '2.0', method: 'evm_increaseTime', params: [duration], diff --git a/test/helpers/web3.js b/test/helpers/web3.js index b4fd87199..b6cd493e1 100644 --- a/test/helpers/web3.js +++ b/test/helpers/web3.js @@ -4,6 +4,7 @@ const ethAsync = pify(web3.eth); module.exports = { ethGetBalance: ethAsync.getBalance, - ethSendTransaction: ethAsync.sendTransaction, ethGetBlock: ethAsync.getBlock, + ethGetTransactionReceipt: ethAsync.getTransactionReceipt, + ethSendTransaction: ethAsync.sendTransaction, }; From 5caecf548c04c97955b8f0487ceb804fab0e2ca1 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Thu, 6 Dec 2018 02:15:27 +0530 Subject: [PATCH 178/205] getter added for an array of tokens held by an owner (#1522) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * conflict fixes * fixes #1512 * Update test/token/ERC721/ERC721Full.test.js Co-Authored-By: Aniket-Engg <30843294+Aniket-Engg@users.noreply.github.com> --- contracts/mocks/ERC721FullMock.sol | 8 ++++++-- contracts/token/ERC721/ERC721Enumerable.sol | 9 +++++++++ test/token/ERC721/ERC721Full.test.js | 9 +++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index 5199ef417..669997557 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -7,8 +7,8 @@ import "../token/ERC721/ERC721Burnable.sol"; /** * @title ERC721FullMock - * This mock just provides a public mint and burn functions for testing purposes, - * and a public setter for metadata URI + * This mock just provides public functions for setting metadata URI, getting all tokens of an owner, + * checking token existence, removal of a token from an address */ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { constructor (string name, string symbol) public ERC721Mintable() ERC721Full(name, symbol) {} @@ -17,6 +17,10 @@ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, E return _exists(tokenId); } + function tokensOfOwner(address owner) public view returns (uint256[] memory) { + return _tokensOfOwner(owner); + } + function setTokenURI(uint256 tokenId, string uri) public { _setTokenURI(tokenId, uri); } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index ff8c1b9ee..95622b759 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -144,4 +144,13 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { _allTokensIndex[tokenId] = 0; _allTokensIndex[lastToken] = tokenIndex; } + + /** + * @dev Gets the list of token IDs of the requested owner + * @param owner address owning the tokens + * @return uint256[] List of token IDs owned by the requested address + */ + function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { + return _ownedTokens[owner]; + } } diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index 6789ca28a..933f624ee 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -138,6 +138,15 @@ contract('ERC721Full', function ([ }); }); + describe('tokensOfOwner', function () { + it('returns total tokens of owner', async function () { + const tokenIds = await this.token.tokensOfOwner(owner); + tokenIds.length.should.equal(2); + tokenIds[0].should.be.bignumber.equal(firstTokenId); + tokenIds[1].should.be.bignumber.equal(secondTokenId); + }); + }); + describe('totalSupply', function () { it('returns total token supply', async function () { (await this.token.totalSupply()).should.be.bignumber.equal(2); From 70fd243e3b7b38e761fd0581ed00537356ed6e41 Mon Sep 17 00:00:00 2001 From: Aniket <30843294+Aniket-Engg@users.noreply.github.com> Date: Fri, 7 Dec 2018 22:02:48 +0530 Subject: [PATCH 179/205] Test setup helper added (#1482) * signing prefix added * Minor improvement * Tests changed * Successfully tested * Minor improvements * Minor improvements * Revert "Dangling commas are now required. (#1359)" This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d. * updates * fixes #1404 * approve failing test * suggested changes done * ISafeERC20 removed * conflict fixes * fixes #1205 * minor change * suggested changes * reviewed changes * final update --- test/access/Roles.test.js | 3 +-- test/access/roles/PublicRole.behavior.js | 3 +-- test/crowdsale/AllowanceCrowdsale.test.js | 6 +----- test/crowdsale/CappedCrowdsale.test.js | 6 +----- test/crowdsale/Crowdsale.test.js | 6 +----- test/crowdsale/FinalizableCrowdsale.test.js | 6 +----- test/crowdsale/IncreasingPriceCrowdsale.test.js | 6 +----- test/crowdsale/IndividuallyCappedCrowdsale.test.js | 6 +----- test/crowdsale/MintedCrowdsale.behavior.js | 6 +----- test/crowdsale/MintedCrowdsale.test.js | 2 +- test/crowdsale/PostDeliveryCrowdsale.test.js | 6 +----- test/crowdsale/RefundableCrowdsale.test.js | 6 +----- test/crowdsale/TimedCrowdsale.test.js | 6 +----- test/cryptography/ECDSA.test.js | 3 +-- test/cryptography/MerkleProof.test.js | 3 +-- test/drafts/Counter.test.js | 4 +--- test/drafts/ERC1046/TokenMetadata.test.js | 3 +-- test/drafts/ERC20Migrator.test.js | 6 +----- test/drafts/SignatureBouncer.test.js | 6 +----- test/drafts/TokenVesting.test.js | 6 +----- test/examples/SampleCrowdsale.test.js | 6 +----- test/examples/SimpleToken.test.js | 6 +----- test/helpers/expectEvent.js | 7 ++----- test/helpers/setup.js | 9 +++++++++ test/helpers/shouldFail.js | 3 +-- test/helpers/test/expectEvent.test.js | 5 +---- test/introspection/ERC165Checker.test.js | 3 +-- test/lifecycle/Pausable.test.js | 6 +----- test/math/Math.test.js | 6 +----- test/math/SafeMath.test.js | 5 +---- test/ownership/Ownable.behavior.js | 4 +--- test/ownership/Secondary.test.js | 3 +-- test/payment/PaymentSplitter.test.js | 6 +----- test/payment/PullPayment.test.js | 6 +----- test/payment/escrow/ConditionalEscrow.test.js | 6 +----- test/payment/escrow/Escrow.behavior.js | 6 +----- test/payment/escrow/RefundEscrow.test.js | 6 +----- test/token/ERC20/ERC20.test.js | 6 +----- test/token/ERC20/ERC20Detailed.test.js | 6 +----- test/token/ERC20/SafeERC20.test.js | 3 +-- test/token/ERC20/TokenTimelock.test.js | 6 +----- test/token/ERC20/behaviors/ERC20Burnable.behavior.js | 6 +----- test/token/ERC20/behaviors/ERC20Capped.behavior.js | 6 +----- test/token/ERC20/behaviors/ERC20Mintable.behavior.js | 6 +----- test/token/ERC721/ERC721.behavior.js | 6 +----- test/token/ERC721/ERC721.test.js | 5 +---- test/token/ERC721/ERC721Burnable.test.js | 5 +---- test/token/ERC721/ERC721Full.test.js | 5 +---- test/token/ERC721/ERC721Holder.test.js | 3 +-- test/token/ERC721/ERC721MintBurn.behavior.js | 6 +----- test/token/ERC721/ERC721Mintable.test.js | 5 +---- test/token/ERC721/ERC721Pausable.test.js | 5 +---- test/token/ERC721/ERC721PausedToken.behavior.js | 6 +----- test/utils/Address.test.js | 3 +-- test/utils/Arrays.test.js | 6 +----- test/utils/ReentrancyGuard.test.js | 6 +----- 56 files changed, 65 insertions(+), 227 deletions(-) create mode 100644 test/helpers/setup.js diff --git a/test/access/Roles.test.js b/test/access/Roles.test.js index 4a3c7b09f..15fffec34 100644 --- a/test/access/Roles.test.js +++ b/test/access/Roles.test.js @@ -3,8 +3,7 @@ const { ZERO_ADDRESS } = require('../helpers/constants'); const RolesMock = artifacts.require('RolesMock'); -require('chai') - .should(); +require('./../helpers/setup'); contract('Roles', function ([_, authorized, otherAuthorized, anyone]) { beforeEach(async function () { diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index 996f843d1..c18b60974 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -2,8 +2,7 @@ const shouldFail = require('../../helpers/shouldFail'); const { ZERO_ADDRESS } = require('../../helpers/constants'); const expectEvent = require('../../helpers/expectEvent'); -require('chai') - .should(); +require('../../helpers/setup'); function capitalize (str) { return str.replace(/\b\w/g, l => l.toUpperCase()); diff --git a/test/crowdsale/AllowanceCrowdsale.test.js b/test/crowdsale/AllowanceCrowdsale.test.js index 5f4c0ad30..4a53c5f97 100644 --- a/test/crowdsale/AllowanceCrowdsale.test.js +++ b/test/crowdsale/AllowanceCrowdsale.test.js @@ -4,11 +4,7 @@ const shouldFail = require('../helpers/shouldFail'); const { balanceDifference } = require('../helpers/balanceDifference'); const { ZERO_ADDRESS } = require('../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const AllowanceCrowdsaleImpl = artifacts.require('AllowanceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index a073d7a4e..8199ec32e 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -1,11 +1,7 @@ const { ether } = require('../helpers/ether'); const shouldFail = require('../helpers/shouldFail'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const CappedCrowdsaleImpl = artifacts.require('CappedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index c2646db9b..dbd33f1aa 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -4,11 +4,7 @@ const { balanceDifference } = require('../helpers/balanceDifference'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const Crowdsale = artifacts.require('CrowdsaleMock'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 48b71d51d..778dbcb98 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -2,11 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const FinalizableCrowdsaleImpl = artifacts.require('FinalizableCrowdsaleImpl'); const ERC20 = artifacts.require('ERC20'); diff --git a/test/crowdsale/IncreasingPriceCrowdsale.test.js b/test/crowdsale/IncreasingPriceCrowdsale.test.js index 34b476186..c9ba167ea 100644 --- a/test/crowdsale/IncreasingPriceCrowdsale.test.js +++ b/test/crowdsale/IncreasingPriceCrowdsale.test.js @@ -2,11 +2,7 @@ const { ether } = require('../helpers/ether'); const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const IncreasingPriceCrowdsaleImpl = artifacts.require('IncreasingPriceCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/IndividuallyCappedCrowdsale.test.js b/test/crowdsale/IndividuallyCappedCrowdsale.test.js index c92fad466..36de85f04 100644 --- a/test/crowdsale/IndividuallyCappedCrowdsale.test.js +++ b/test/crowdsale/IndividuallyCappedCrowdsale.test.js @@ -1,11 +1,7 @@ const { ether } = require('../helpers/ether'); const shouldFail = require('../helpers/shouldFail'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const IndividuallyCappedCrowdsaleImpl = artifacts.require('IndividuallyCappedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/MintedCrowdsale.behavior.js b/test/crowdsale/MintedCrowdsale.behavior.js index e58d54aa6..ec41e4948 100644 --- a/test/crowdsale/MintedCrowdsale.behavior.js +++ b/test/crowdsale/MintedCrowdsale.behavior.js @@ -1,11 +1,7 @@ const expectEvent = require('../helpers/expectEvent'); const { balanceDifference } = require('../helpers/balanceDifference'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); function shouldBehaveLikeMintedCrowdsale ([_, investor, wallet, purchaser], rate, value) { const expectedTokenAmount = rate.mul(value); diff --git a/test/crowdsale/MintedCrowdsale.test.js b/test/crowdsale/MintedCrowdsale.test.js index 0b95f9ab8..98e54646d 100644 --- a/test/crowdsale/MintedCrowdsale.test.js +++ b/test/crowdsale/MintedCrowdsale.test.js @@ -2,7 +2,7 @@ const { shouldBehaveLikeMintedCrowdsale } = require('./MintedCrowdsale.behavior' const { ether } = require('../helpers/ether'); const shouldFail = require('../helpers/shouldFail'); -const BigNumber = web3.BigNumber; +const { BigNumber } = require('../helpers/setup'); const MintedCrowdsaleImpl = artifacts.require('MintedCrowdsaleImpl'); const ERC20Mintable = artifacts.require('ERC20Mintable'); diff --git a/test/crowdsale/PostDeliveryCrowdsale.test.js b/test/crowdsale/PostDeliveryCrowdsale.test.js index 58d8c1123..e1e3b40a5 100644 --- a/test/crowdsale/PostDeliveryCrowdsale.test.js +++ b/test/crowdsale/PostDeliveryCrowdsale.test.js @@ -2,11 +2,7 @@ const time = require('../helpers/time'); const shouldFail = require('../helpers/shouldFail'); const { ether } = require('../helpers/ether'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const PostDeliveryCrowdsaleImpl = artifacts.require('PostDeliveryCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index ce16f66f5..9c8d01c72 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -4,11 +4,7 @@ const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); const { ethGetBalance } = require('../helpers/web3'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const RefundableCrowdsaleImpl = artifacts.require('RefundableCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/crowdsale/TimedCrowdsale.test.js b/test/crowdsale/TimedCrowdsale.test.js index 4689ad820..2f6e3e15c 100644 --- a/test/crowdsale/TimedCrowdsale.test.js +++ b/test/crowdsale/TimedCrowdsale.test.js @@ -2,11 +2,7 @@ const { ether } = require('../helpers/ether'); const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const TimedCrowdsaleImpl = artifacts.require('TimedCrowdsaleImpl'); const SimpleToken = artifacts.require('SimpleToken'); diff --git a/test/cryptography/ECDSA.test.js b/test/cryptography/ECDSA.test.js index b07178b20..1909b848d 100644 --- a/test/cryptography/ECDSA.test.js +++ b/test/cryptography/ECDSA.test.js @@ -3,8 +3,7 @@ const shouldFail = require('../helpers/shouldFail'); const ECDSAMock = artifacts.require('ECDSAMock'); -require('chai') - .should(); +require('../helpers/setup'); const TEST_MESSAGE = web3.sha3('OpenZeppelin'); const WRONG_MESSAGE = web3.sha3('Nope'); diff --git a/test/cryptography/MerkleProof.test.js b/test/cryptography/MerkleProof.test.js index 8940b240c..869423048 100644 --- a/test/cryptography/MerkleProof.test.js +++ b/test/cryptography/MerkleProof.test.js @@ -3,8 +3,7 @@ const { keccak256, bufferToHex } = require('ethereumjs-util'); const MerkleProofWrapper = artifacts.require('MerkleProofWrapper'); -require('chai') - .should(); +require('../helpers/setup'); contract('MerkleProof', function () { beforeEach(async function () { diff --git a/test/drafts/Counter.test.js b/test/drafts/Counter.test.js index 8a2929d93..008e76778 100644 --- a/test/drafts/Counter.test.js +++ b/test/drafts/Counter.test.js @@ -1,9 +1,7 @@ const CounterImpl = artifacts.require('CounterImpl'); -require('chai') - .use(require('chai-bignumber')(web3.BigNumber)) - .should(); +require('../helpers/setup'); const EXPECTED = [1, 2, 3, 4]; const KEY1 = web3.sha3('key1'); diff --git a/test/drafts/ERC1046/TokenMetadata.test.js b/test/drafts/ERC1046/TokenMetadata.test.js index 9810d9119..58aaa3a33 100644 --- a/test/drafts/ERC1046/TokenMetadata.test.js +++ b/test/drafts/ERC1046/TokenMetadata.test.js @@ -1,7 +1,6 @@ const ERC20WithMetadataMock = artifacts.require('ERC20WithMetadataMock'); -require('chai') - .should(); +require('../../helpers/setup'); const metadataURI = 'https://example.com'; diff --git a/test/drafts/ERC20Migrator.test.js b/test/drafts/ERC20Migrator.test.js index 92763a219..05c8f5f03 100644 --- a/test/drafts/ERC20Migrator.test.js +++ b/test/drafts/ERC20Migrator.test.js @@ -5,11 +5,7 @@ const ERC20Mock = artifacts.require('ERC20Mock'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const ERC20Migrator = artifacts.require('ERC20Migrator'); -const BigNumber = web3.eth.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) { const totalSupply = 200; diff --git a/test/drafts/SignatureBouncer.test.js b/test/drafts/SignatureBouncer.test.js index e1bb294f3..4e204011a 100644 --- a/test/drafts/SignatureBouncer.test.js +++ b/test/drafts/SignatureBouncer.test.js @@ -4,11 +4,7 @@ const { shouldBehaveLikePublicRole } = require('../access/roles/PublicRole.behav const SignatureBouncerMock = artifacts.require('SignatureBouncerMock'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); const UINT_VALUE = 23; const BYTES_VALUE = web3.toHex('test'); diff --git a/test/drafts/TokenVesting.test.js b/test/drafts/TokenVesting.test.js index be872ae22..cb8fc18b5 100644 --- a/test/drafts/TokenVesting.test.js +++ b/test/drafts/TokenVesting.test.js @@ -4,11 +4,7 @@ const time = require('../helpers/time'); const { ethGetBlock } = require('../helpers/web3'); const { ZERO_ADDRESS } = require('../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const TokenVesting = artifacts.require('TokenVesting'); diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index 51df3c40e..e768265b4 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -3,11 +3,7 @@ const shouldFail = require('../helpers/shouldFail'); const time = require('../helpers/time'); const { balanceDifference } = require('../helpers/balanceDifference'); -const BigNumber = web3.BigNumber; - -const should = require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { should, BigNumber } = require('../helpers/setup'); const SampleCrowdsale = artifacts.require('SampleCrowdsale'); const SampleCrowdsaleToken = artifacts.require('SampleCrowdsaleToken'); diff --git a/test/examples/SimpleToken.test.js b/test/examples/SimpleToken.test.js index 091f31715..540ce4ae0 100644 --- a/test/examples/SimpleToken.test.js +++ b/test/examples/SimpleToken.test.js @@ -2,11 +2,7 @@ const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); const SimpleToken = artifacts.require('SimpleToken'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); contract('SimpleToken', function ([_, creator]) { beforeEach(async function () { diff --git a/test/helpers/expectEvent.js b/test/helpers/expectEvent.js index 3cb6b37ec..29d1027c3 100644 --- a/test/helpers/expectEvent.js +++ b/test/helpers/expectEvent.js @@ -1,11 +1,8 @@ +const { should, BigNumber } = require('./setup'); + const SolidityEvent = require('web3/lib/web3/event.js'); const { ethGetTransactionReceipt } = require('./web3'); -const BigNumber = web3.BigNumber; -const should = require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); - function inLogs (logs, eventName, eventArgs = {}) { const event = logs.find(function (e) { if (e.event === eventName) { diff --git a/test/helpers/setup.js b/test/helpers/setup.js new file mode 100644 index 000000000..d27794d5e --- /dev/null +++ b/test/helpers/setup.js @@ -0,0 +1,9 @@ +const chai = require('chai'); + +const BigNumber = web3.BigNumber; +const should = chai.use(require('chai-bignumber')(BigNumber)).should(); + +module.exports = { + BigNumber, + should, +}; diff --git a/test/helpers/shouldFail.js b/test/helpers/shouldFail.js index a64e1a59c..139339c7e 100644 --- a/test/helpers/shouldFail.js +++ b/test/helpers/shouldFail.js @@ -1,5 +1,4 @@ -const should = require('chai') - .should(); +const { should } = require('./setup'); async function shouldFailWithMessage (promise, message) { try { diff --git a/test/helpers/test/expectEvent.test.js b/test/helpers/test/expectEvent.test.js index c5d09a4ed..4dd81560f 100644 --- a/test/helpers/test/expectEvent.test.js +++ b/test/helpers/test/expectEvent.test.js @@ -4,10 +4,7 @@ const shouldFail = require('../shouldFail'); const EventEmitter = artifacts.require('EventEmitter'); const IndirectEventEmitter = artifacts.require('IndirectEventEmitter'); -const BigNumber = web3.BigNumber; -const should = require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { should, BigNumber } = require('../../helpers/setup'); describe('expectEvent', function () { beforeEach(async function () { diff --git a/test/introspection/ERC165Checker.test.js b/test/introspection/ERC165Checker.test.js index 7f5dc9fc5..c339c78ab 100644 --- a/test/introspection/ERC165Checker.test.js +++ b/test/introspection/ERC165Checker.test.js @@ -9,8 +9,7 @@ const DUMMY_UNSUPPORTED_ID = '0xbaddcafe'; const DUMMY_UNSUPPORTED_ID_2 = '0xbaadcafe'; const DUMMY_ACCOUNT = '0x1111111111111111111111111111111111111111'; -require('chai') - .should(); +require('../helpers/setup'); contract('ERC165Checker', function () { beforeEach(async function () { diff --git a/test/lifecycle/Pausable.test.js b/test/lifecycle/Pausable.test.js index f279e09a7..7b8d3e8cb 100644 --- a/test/lifecycle/Pausable.test.js +++ b/test/lifecycle/Pausable.test.js @@ -4,11 +4,7 @@ const expectEvent = require('../helpers/expectEvent'); const PausableMock = artifacts.require('PausableMock'); const { shouldBehaveLikePublicRole } = require('../access/roles/PublicRole.behavior'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts]) { beforeEach(async function () { diff --git a/test/math/Math.test.js b/test/math/Math.test.js index 3e801d0e9..99ab04531 100644 --- a/test/math/Math.test.js +++ b/test/math/Math.test.js @@ -1,10 +1,6 @@ const MathMock = artifacts.require('MathMock'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); contract('Math', function () { const min = 1234; diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index 47e8559ef..b006e06e1 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,12 +1,9 @@ const shouldFail = require('../helpers/shouldFail'); const { MAX_UINT256 } = require('../helpers/constants'); -const BigNumber = web3.BigNumber; const SafeMathMock = artifacts.require('SafeMathMock'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../helpers/setup'); contract('SafeMath', function () { beforeEach(async function () { diff --git a/test/ownership/Ownable.behavior.js b/test/ownership/Ownable.behavior.js index dd6007cef..a23030d0b 100644 --- a/test/ownership/Ownable.behavior.js +++ b/test/ownership/Ownable.behavior.js @@ -1,9 +1,7 @@ const shouldFail = require('../helpers/shouldFail'); const expectEvent = require('../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../helpers/constants'); - -require('chai') - .should(); +require('./../helpers/setup'); function shouldBehaveLikeOwnable (owner, [anyone]) { describe('as an ownable', function () { diff --git a/test/ownership/Secondary.test.js b/test/ownership/Secondary.test.js index c8772db1f..cbc96320a 100644 --- a/test/ownership/Secondary.test.js +++ b/test/ownership/Secondary.test.js @@ -4,8 +4,7 @@ const { ZERO_ADDRESS } = require('../helpers/constants'); const SecondaryMock = artifacts.require('SecondaryMock'); -require('chai') - .should(); +require('../helpers/setup'); contract('Secondary', function ([_, primary, newPrimary, anyone]) { beforeEach(async function () { diff --git a/test/payment/PaymentSplitter.test.js b/test/payment/PaymentSplitter.test.js index 34404536e..58c1712db 100644 --- a/test/payment/PaymentSplitter.test.js +++ b/test/payment/PaymentSplitter.test.js @@ -4,11 +4,7 @@ const send = require('./../helpers/send'); const { ether } = require('../helpers/ether'); const { ZERO_ADDRESS } = require('./../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); const shouldFail = require('../helpers/shouldFail'); const PaymentSplitter = artifacts.require('PaymentSplitter'); diff --git a/test/payment/PullPayment.test.js b/test/payment/PullPayment.test.js index 13b27ff01..f82712ef3 100644 --- a/test/payment/PullPayment.test.js +++ b/test/payment/PullPayment.test.js @@ -1,11 +1,7 @@ const { balanceDifference } = require('../helpers/balanceDifference'); const { ether } = require('../helpers/ether'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); const PullPaymentMock = artifacts.require('PullPaymentMock'); diff --git a/test/payment/escrow/ConditionalEscrow.test.js b/test/payment/escrow/ConditionalEscrow.test.js index c30b7bde5..bb5b5cf98 100644 --- a/test/payment/escrow/ConditionalEscrow.test.js +++ b/test/payment/escrow/ConditionalEscrow.test.js @@ -3,11 +3,7 @@ const { shouldBehaveLikeEscrow } = require('./Escrow.behavior'); const shouldFail = require('../../helpers/shouldFail'); const { ether } = require('../../helpers/ether'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); const ConditionalEscrowMock = artifacts.require('ConditionalEscrowMock'); diff --git a/test/payment/escrow/Escrow.behavior.js b/test/payment/escrow/Escrow.behavior.js index 7dd0918a4..80bde2f5c 100644 --- a/test/payment/escrow/Escrow.behavior.js +++ b/test/payment/escrow/Escrow.behavior.js @@ -4,11 +4,7 @@ const { ethGetBalance } = require('../../helpers/web3'); const { balanceDifference } = require('../../helpers/balanceDifference'); const { ether } = require('../../helpers/ether'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); function shouldBehaveLikeEscrow (primary, [payee1, payee2]) { const amount = ether(42.0); diff --git a/test/payment/escrow/RefundEscrow.test.js b/test/payment/escrow/RefundEscrow.test.js index bb5189ddc..c0a9f8f04 100644 --- a/test/payment/escrow/RefundEscrow.test.js +++ b/test/payment/escrow/RefundEscrow.test.js @@ -4,11 +4,7 @@ const { balanceDifference } = require('../../helpers/balanceDifference'); const { ether } = require('../../helpers/ether'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); const RefundEscrow = artifacts.require('RefundEscrow'); diff --git a/test/token/ERC20/ERC20.test.js b/test/token/ERC20/ERC20.test.js index 42bd872fd..16d2cab75 100644 --- a/test/token/ERC20/ERC20.test.js +++ b/test/token/ERC20/ERC20.test.js @@ -4,11 +4,7 @@ const { ZERO_ADDRESS } = require('../../helpers/constants'); const ERC20Mock = artifacts.require('ERC20Mock'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../../helpers/setup'); contract('ERC20', function ([_, owner, recipient, anotherAccount]) { beforeEach(async function () { diff --git a/test/token/ERC20/ERC20Detailed.test.js b/test/token/ERC20/ERC20Detailed.test.js index 7965b7e9d..448487acd 100644 --- a/test/token/ERC20/ERC20Detailed.test.js +++ b/test/token/ERC20/ERC20Detailed.test.js @@ -1,8 +1,4 @@ -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); const ERC20DetailedMock = artifacts.require('ERC20DetailedMock'); diff --git a/test/token/ERC20/SafeERC20.test.js b/test/token/ERC20/SafeERC20.test.js index c8dea7382..4be44cf38 100644 --- a/test/token/ERC20/SafeERC20.test.js +++ b/test/token/ERC20/SafeERC20.test.js @@ -1,7 +1,6 @@ const shouldFail = require('../../helpers/shouldFail'); -require('chai') - .should(); +require('../../helpers/setup'); const SafeERC20Helper = artifacts.require('SafeERC20Helper'); diff --git a/test/token/ERC20/TokenTimelock.test.js b/test/token/ERC20/TokenTimelock.test.js index 1816bf902..6669e7487 100644 --- a/test/token/ERC20/TokenTimelock.test.js +++ b/test/token/ERC20/TokenTimelock.test.js @@ -1,11 +1,7 @@ const shouldFail = require('../../helpers/shouldFail'); const time = require('../../helpers/time'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +const { BigNumber } = require('../../helpers/setup'); const ERC20Mintable = artifacts.require('ERC20Mintable'); const TokenTimelock = artifacts.require('TokenTimelock'); diff --git a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js index 6e550afcb..6d1c7195b 100644 --- a/test/token/ERC20/behaviors/ERC20Burnable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Burnable.behavior.js @@ -2,11 +2,7 @@ const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../../helpers/setup'); function shouldBehaveLikeERC20Burnable (owner, initialBalance, [burner]) { describe('burn', function () { diff --git a/test/token/ERC20/behaviors/ERC20Capped.behavior.js b/test/token/ERC20/behaviors/ERC20Capped.behavior.js index e61db5702..876dbd329 100644 --- a/test/token/ERC20/behaviors/ERC20Capped.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Capped.behavior.js @@ -1,10 +1,6 @@ const shouldFail = require('../../../helpers/shouldFail'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../../helpers/setup'); function shouldBehaveLikeERC20Capped (minter, [anyone], cap) { describe('capped token', function () { diff --git a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js index bb8c0fe30..987b67752 100644 --- a/test/token/ERC20/behaviors/ERC20Mintable.behavior.js +++ b/test/token/ERC20/behaviors/ERC20Mintable.behavior.js @@ -2,11 +2,7 @@ const shouldFail = require('../../../helpers/shouldFail'); const expectEvent = require('../../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../../helpers/setup'); function shouldBehaveLikeERC20Mintable (minter, [anyone]) { describe('as a mintable token', function () { diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index d350c3f6c..b7600872c 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -5,11 +5,7 @@ const { ZERO_ADDRESS } = require('../../helpers/constants'); const send = require('../../helpers/send'); const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); function shouldBehaveLikeERC721 ( creator, diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index eef76eba8..87e895f14 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -1,11 +1,8 @@ const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); -const BigNumber = web3.BigNumber; const ERC721Mock = artifacts.require('ERC721Mock.sol'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); contract('ERC721', function ([_, creator, ...accounts]) { beforeEach(async function () { diff --git a/test/token/ERC721/ERC721Burnable.test.js b/test/token/ERC721/ERC721Burnable.test.js index 745f7dac2..a75e60ff8 100644 --- a/test/token/ERC721/ERC721Burnable.test.js +++ b/test/token/ERC721/ERC721Burnable.test.js @@ -3,12 +3,9 @@ const { shouldBehaveLikeMintAndBurnERC721, } = require('./ERC721MintBurn.behavior'); -const BigNumber = web3.BigNumber; const ERC721BurnableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); contract('ERC721Burnable', function ([_, creator, ...accounts]) { const minter = creator; diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index 933f624ee..3870a95f6 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -2,12 +2,9 @@ const shouldFail = require('../../helpers/shouldFail'); const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior'); -const BigNumber = web3.BigNumber; const ERC721FullMock = artifacts.require('ERC721FullMock.sol'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); contract('ERC721Full', function ([ creator, diff --git a/test/token/ERC721/ERC721Holder.test.js b/test/token/ERC721/ERC721Holder.test.js index 9f6eb856a..1c0b0dcdf 100644 --- a/test/token/ERC721/ERC721Holder.test.js +++ b/test/token/ERC721/ERC721Holder.test.js @@ -1,8 +1,7 @@ const ERC721Holder = artifacts.require('ERC721Holder.sol'); const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol'); -require('chai') - .should(); +require('../../helpers/setup'); contract('ERC721Holder', function ([creator]) { it('receives an ERC721 token', async function () { diff --git a/test/token/ERC721/ERC721MintBurn.behavior.js b/test/token/ERC721/ERC721MintBurn.behavior.js index 1bb7d1bc7..97c33ae36 100644 --- a/test/token/ERC721/ERC721MintBurn.behavior.js +++ b/test/token/ERC721/ERC721MintBurn.behavior.js @@ -1,11 +1,7 @@ const shouldFail = require('../../helpers/shouldFail'); const expectEvent = require('../../helpers/expectEvent'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); function shouldBehaveLikeMintAndBurnERC721 ( creator, diff --git a/test/token/ERC721/ERC721Mintable.test.js b/test/token/ERC721/ERC721Mintable.test.js index 639c8374d..97a129efb 100644 --- a/test/token/ERC721/ERC721Mintable.test.js +++ b/test/token/ERC721/ERC721Mintable.test.js @@ -3,12 +3,9 @@ const { shouldBehaveLikeMintAndBurnERC721, } = require('./ERC721MintBurn.behavior'); -const BigNumber = web3.BigNumber; const ERC721MintableImpl = artifacts.require('ERC721MintableBurnableImpl.sol'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); contract('ERC721Mintable', function ([_, creator, ...accounts]) { const minter = creator; diff --git a/test/token/ERC721/ERC721Pausable.test.js b/test/token/ERC721/ERC721Pausable.test.js index 3961368ef..ca728001d 100644 --- a/test/token/ERC721/ERC721Pausable.test.js +++ b/test/token/ERC721/ERC721Pausable.test.js @@ -2,12 +2,9 @@ const { shouldBehaveLikeERC721PausedToken } = require('./ERC721PausedToken.behav const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); -const BigNumber = web3.BigNumber; const ERC721PausableMock = artifacts.require('ERC721PausableMock.sol'); -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); contract('ERC721Pausable', function ([ _, diff --git a/test/token/ERC721/ERC721PausedToken.behavior.js b/test/token/ERC721/ERC721PausedToken.behavior.js index d44bc0565..6df4b0cc4 100644 --- a/test/token/ERC721/ERC721PausedToken.behavior.js +++ b/test/token/ERC721/ERC721PausedToken.behavior.js @@ -2,11 +2,7 @@ const shouldFail = require('../../helpers/shouldFail'); const send = require('../../helpers/send'); const { ZERO_ADDRESS } = require('../../helpers/constants'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../../helpers/setup'); function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) { const firstTokenId = 1; diff --git a/test/utils/Address.test.js b/test/utils/Address.test.js index f41e57565..23c2b1dfb 100644 --- a/test/utils/Address.test.js +++ b/test/utils/Address.test.js @@ -1,8 +1,7 @@ const AddressImpl = artifacts.require('AddressImpl'); const SimpleToken = artifacts.require('SimpleToken'); -require('chai') - .should(); +require('../helpers/setup'); contract('Address', function ([_, anyone]) { beforeEach(async function () { diff --git a/test/utils/Arrays.test.js b/test/utils/Arrays.test.js index 4bfc9eaba..1c9bfdfc0 100644 --- a/test/utils/Arrays.test.js +++ b/test/utils/Arrays.test.js @@ -1,10 +1,6 @@ const ArraysImpl = artifacts.require('ArraysImpl'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); contract('Arrays', function () { context('Even number of elements', function () { diff --git a/test/utils/ReentrancyGuard.test.js b/test/utils/ReentrancyGuard.test.js index 16706fe8e..c6da57a95 100644 --- a/test/utils/ReentrancyGuard.test.js +++ b/test/utils/ReentrancyGuard.test.js @@ -2,11 +2,7 @@ const shouldFail = require('../helpers/shouldFail'); const ReentrancyMock = artifacts.require('ReentrancyMock'); const ReentrancyAttack = artifacts.require('ReentrancyAttack'); -const BigNumber = web3.BigNumber; - -require('chai') - .use(require('chai-bignumber')(BigNumber)) - .should(); +require('../helpers/setup'); contract('ReentrancyGuard', function () { beforeEach(async function () { From 70e616db7c2bcce9d3a3fbbab83b7fe64a54fcd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 11 Dec 2018 12:51:26 -0300 Subject: [PATCH 180/205] Optimized ERC721 transfers. (#1539) * Added _transferToken. * _transferFrom is now usable by derived contracts, abstracted away enumerable behavior. * Removed unnecesary check from _clearApprovals --- contracts/token/ERC721/ERC721.sol | 35 ++++++--- contracts/token/ERC721/ERC721Enumerable.sol | 81 ++++++++++++++++----- 2 files changed, 87 insertions(+), 29 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index d64c97b32..e0557ddbf 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -130,13 +130,8 @@ contract ERC721 is ERC165, IERC721 { */ function transferFrom(address from, address to, uint256 tokenId) public { require(_isApprovedOrOwner(msg.sender, tokenId)); - require(to != address(0)); - _clearApproval(from, tokenId); - _removeTokenFrom(from, tokenId); - _addTokenTo(to, tokenId); - - emit Transfer(from, to, tokenId); + _transferFrom(from, to, tokenId); } /** @@ -217,7 +212,7 @@ contract ERC721 is ERC165, IERC721 { * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { - _clearApproval(owner, tokenId); + _clearApproval(tokenId); _removeTokenFrom(owner, tokenId); emit Transfer(owner, address(0), tokenId); } @@ -249,6 +244,27 @@ contract ERC721 is ERC165, IERC721 { _tokenOwner[tokenId] = address(0); } + /** + * @dev Internal function to transfer ownership of a given token ID to another address. + * As opposed to transferFrom, this imposes no restrictions on msg.sender. + * @param from current owner of the token + * @param to address to receive the ownership of the given token ID + * @param tokenId uint256 ID of the token to be transferred + */ + function _transferFrom(address from, address to, uint256 tokenId) internal { + require(ownerOf(tokenId) == from); + require(to != address(0)); + + _clearApproval(tokenId); + + _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); + _ownedTokensCount[to] = _ownedTokensCount[to].add(1); + + _tokenOwner[tokenId] = to; + + emit Transfer(from, to, tokenId); + } + /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract @@ -269,12 +285,9 @@ contract ERC721 is ERC165, IERC721 { /** * @dev Private function to clear current approval of a given token ID - * Reverts if the given address is not indeed the owner of the token - * @param owner owner of the token * @param tokenId uint256 ID of the token to be transferred */ - function _clearApproval(address owner, uint256 tokenId) private { - require(ownerOf(tokenId) == owner); + function _clearApproval(uint256 tokenId) private { if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index 95622b759..441624c02 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -76,9 +76,8 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { */ function _addTokenTo(address to, uint256 tokenId) internal { super._addTokenTo(to, tokenId); - uint256 length = _ownedTokens[to].length; - _ownedTokens[to].push(tokenId); - _ownedTokensIndex[tokenId] = length; + + _addTokenToOwnerEnumeration(to, tokenId); } /** @@ -92,22 +91,26 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { function _removeTokenFrom(address from, uint256 tokenId) internal { super._removeTokenFrom(from, tokenId); - // To prevent a gap in the array, we store the last token in the index of the token to delete, and - // then delete the last slot. - uint256 tokenIndex = _ownedTokensIndex[tokenId]; - uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); - uint256 lastToken = _ownedTokens[from][lastTokenIndex]; - - _ownedTokens[from][tokenIndex] = lastToken; - // This also deletes the contents at the last position of the array - _ownedTokens[from].length--; - - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to - // be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping - // the lastToken to the first position, and then dropping the element placed in the last position of the list + _removeTokenFromOwnerEnumeration(from, tokenId); + // Since the token is being destroyed, we also clear its index + // TODO(nventuro): 0 is still a valid index, so arguably this isnt really helpful, remove? _ownedTokensIndex[tokenId] = 0; - _ownedTokensIndex[lastToken] = tokenIndex; + } + + /** + * @dev Internal function to transfer ownership of a given token ID to another address. + * As opposed to transferFrom, this imposes no restrictions on msg.sender. + * @param from current owner of the token + * @param to address to receive the ownership of the given token ID + * @param tokenId uint256 ID of the token to be transferred + */ + function _transferFrom(address from, address to, uint256 tokenId) internal { + super._transferFrom(from, to, tokenId); + + _removeTokenFromOwnerEnumeration(from, tokenId); + + _addTokenToOwnerEnumeration(to, tokenId); } /** @@ -144,7 +147,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { _allTokensIndex[tokenId] = 0; _allTokensIndex[lastToken] = tokenIndex; } - + /** * @dev Gets the list of token IDs of the requested owner * @param owner address owning the tokens @@ -153,4 +156,46 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { return _ownedTokens[owner]; } + + /** + * @dev Private function to add a token to this extension's ownership-tracking data structures. + * @param to address representing the new owner of the given token ID + * @param tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { + uint256 newOwnedTokensLength = _ownedTokens[to].push(tokenId); + // No need to use SafeMath since the length after a push cannot be zero + _ownedTokensIndex[tokenId] = newOwnedTokensLength - 1; + } + + /** + * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that + * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for + * gas optimizations e.g. when performing a transfer operation (avoiding double writes). + * This has O(1) time complexity, but alters the order of the _ownedTokens array. + * @param from address representing the previous owner of the given token ID + * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { + // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and + // then delete the last slot (swap and pop). + + uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); + uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; + + uint256 tokenIndex = _ownedTokensIndex[tokenId]; + + _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token + _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + + // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going + // to be zero. The swap operation will therefore have no effect, but the token _will_ be deleted during the + // 'pop' operation. + + // This also deletes the contents at the last position of the array + _ownedTokens[from].length--; + + // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occcupied by + // lasTokenId). + } } From 357fded2b591ea37ee35f39bce00d607094beb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 11 Dec 2018 18:07:24 -0300 Subject: [PATCH 181/205] Refundable post delivery crowdsale (#1543) * Fixed unnecessary dependency of RefundableCrowdsaleImpl on ERC20Mintable. * Added PostDeliveryRefundableCrowdsale. * Renamed to RefundablePostDeliveryCrowdsale. * Added deprecation warning. --- .../distribution/RefundableCrowdsale.sol | 22 ++-- .../RefundablePostDeliveryCrowdsale.sol | 20 ++++ contracts/mocks/RefundableCrowdsaleImpl.sol | 4 +- .../RefundablePostDeliveryCrowdsaleImpl.sol | 20 ++++ .../RefundablePostDeliveryCrowdsale.test.js | 103 ++++++++++++++++++ 5 files changed, 152 insertions(+), 17 deletions(-) create mode 100644 contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol create mode 100644 contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol create mode 100644 test/crowdsale/RefundablePostDeliveryCrowdsale.test.js diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index 6c5365cc1..4ef5dffd4 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -6,21 +6,13 @@ import "../../payment/escrow/RefundEscrow.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. - * WARNING: note that if you allow tokens to be traded before the goal - * is met, then an attack is possible in which the attacker purchases - * tokens from the crowdsale and when they sees that the goal is - * unlikely to be met, they sell their tokens (possibly at a discount). - * The attacker will be refunded when the crowdsale is finalized, and - * the users that purchased from them will be left with worthless - * tokens. There are many possible ways to avoid this, like making the - * the crowdsale inherit from PostDeliveryCrowdsale, or imposing - * restrictions on token trading until the crowdsale is finalized. - * This is being discussed in - * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877 - * This contract will be updated when we agree on a general solution - * for this problem. + * @dev Extension of Crowdsale contract that adds a funding goal, and the possibility of users getting a refund if goal + * is not met. + * + * Deprecated, use RefundablePostDeliveryCrowdsale instead. Note that if you allow tokens to be traded before the goal + * is met, then an attack is possible in which the attacker purchases tokens from the crowdsale and when they sees that + * the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when + * the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens. */ contract RefundableCrowdsale is FinalizableCrowdsale { using SafeMath for uint256; diff --git a/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol new file mode 100644 index 000000000..1586a19d1 --- /dev/null +++ b/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.4.24; + +import "./RefundableCrowdsale.sol"; +import "./PostDeliveryCrowdsale.sol"; + + +/** + * @title RefundablePostDeliveryCrowdsale + * @dev Extension of RefundableCrowdsale contract that only delivers the tokens + * once the crowdsale has closed and the goal met, preventing refunds to be issued + * to token holders. + */ +contract RefundablePostDeliveryCrowdsale is RefundableCrowdsale, PostDeliveryCrowdsale { + function withdrawTokens(address beneficiary) public { + require(finalized()); + require(goalReached()); + + super.withdrawTokens(beneficiary); + } +} diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index 6759d9aff..325653b5f 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../token/ERC20/ERC20Mintable.sol"; +import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; contract RefundableCrowdsaleImpl is RefundableCrowdsale { @@ -9,7 +9,7 @@ contract RefundableCrowdsaleImpl is RefundableCrowdsale { uint256 closingTime, uint256 rate, address wallet, - ERC20Mintable token, + IERC20 token, uint256 goal ) public diff --git a/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol new file mode 100644 index 000000000..06f21d71b --- /dev/null +++ b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/IERC20.sol"; +import "../crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol"; + +contract RefundablePostDeliveryCrowdsaleImpl is RefundablePostDeliveryCrowdsale { + constructor ( + uint256 openingTime, + uint256 closingTime, + uint256 rate, + address wallet, + IERC20 token, + uint256 goal + ) + public + Crowdsale(rate, wallet, token) + TimedCrowdsale(openingTime, closingTime) + RefundableCrowdsale(goal) + {} +} diff --git a/test/crowdsale/RefundablePostDeliveryCrowdsale.test.js b/test/crowdsale/RefundablePostDeliveryCrowdsale.test.js new file mode 100644 index 000000000..088c73161 --- /dev/null +++ b/test/crowdsale/RefundablePostDeliveryCrowdsale.test.js @@ -0,0 +1,103 @@ +const time = require('../helpers/time'); +const shouldFail = require('../helpers/shouldFail'); +const { ether } = require('../helpers/ether'); + +const BigNumber = web3.BigNumber; + +require('chai') + .use(require('chai-bignumber')(BigNumber)) + .should(); + +const RefundablePostDeliveryCrowdsaleImpl = artifacts.require('RefundablePostDeliveryCrowdsaleImpl'); +const SimpleToken = artifacts.require('SimpleToken'); + +contract('RefundablePostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) { + const rate = new BigNumber(1); + const tokenSupply = new BigNumber('1e22'); + const goal = ether(100); + + before(async function () { + // Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache + await time.advanceBlock(); + }); + + beforeEach(async function () { + this.openingTime = (await time.latest()) + time.duration.weeks(1); + this.closingTime = this.openingTime + time.duration.weeks(1); + this.afterClosingTime = this.closingTime + time.duration.seconds(1); + this.token = await SimpleToken.new(); + this.crowdsale = await RefundablePostDeliveryCrowdsaleImpl.new( + this.openingTime, this.closingTime, rate, wallet, this.token.address, goal + ); + await this.token.transfer(this.crowdsale.address, tokenSupply); + }); + + context('after opening time', function () { + beforeEach(async function () { + await time.increaseTo(this.openingTime); + }); + + context('with bought tokens below the goal', function () { + const value = goal.sub(1); + + beforeEach(async function () { + await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); + }); + + it('does not immediately deliver tokens to beneficiaries', async function () { + (await this.crowdsale.balanceOf(investor)).should.be.bignumber.equal(value); + (await this.token.balanceOf(investor)).should.be.bignumber.equal(0); + }); + + it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); + }); + + context('after closing time and finalization', function () { + beforeEach(async function () { + await time.increaseTo(this.afterClosingTime); + await this.crowdsale.finalize(); + }); + + it('rejects token withdrawals', async function () { + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); + }); + }); + }); + + context('with bought tokens matching the goal', function () { + const value = goal; + + beforeEach(async function () { + await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); + }); + + it('does not immediately deliver tokens to beneficiaries', async function () { + (await this.crowdsale.balanceOf(investor)).should.be.bignumber.equal(value); + (await this.token.balanceOf(investor)).should.be.bignumber.equal(0); + }); + + it('does not allow beneficiaries to withdraw tokens before crowdsale ends', async function () { + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); + }); + + context('after closing time and finalization', function () { + beforeEach(async function () { + await time.increaseTo(this.afterClosingTime); + await this.crowdsale.finalize(); + }); + + it('allows beneficiaries to withdraw tokens', async function () { + await this.crowdsale.withdrawTokens(investor); + (await this.crowdsale.balanceOf(investor)).should.be.bignumber.equal(0); + (await this.token.balanceOf(investor)).should.be.bignumber.equal(value); + }); + + it('rejects multiple withdrawals', async function () { + await this.crowdsale.withdrawTokens(investor); + await shouldFail.reverting(this.crowdsale.withdrawTokens(investor)); + }); + }); + }); + }); +}); From dd2e94797604a0041140d79f44dbe9a8b7d3233f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 11 Dec 2018 18:07:59 -0300 Subject: [PATCH 182/205] Deprecated ERC721._burn(address, uint256) (#1550) * Deprecated ERC721._burn(address, uint256) * Added missing natspec comment. --- contracts/mocks/ERC721Mock.sol | 2 +- contracts/mocks/ERC721PausableMock.sol | 2 +- contracts/token/ERC721/ERC721.sol | 15 +++++++++++++-- contracts/token/ERC721/ERC721Burnable.sol | 2 +- contracts/token/ERC721/ERC721Enumerable.sol | 9 +++++---- contracts/token/ERC721/ERC721Metadata.sol | 1 + 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index 98bfe99bc..2a429fbae 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -12,6 +12,6 @@ contract ERC721Mock is ERC721 { } function burn(uint256 tokenId) public { - _burn(ownerOf(tokenId), tokenId); + _burn(tokenId); } } diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index 4470ea726..bd6ea8df8 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -13,7 +13,7 @@ contract ERC721PausableMock is ERC721Pausable, PauserRoleMock { } function burn(uint256 tokenId) public { - super._burn(ownerOf(tokenId), tokenId); + super._burn(tokenId); } function exists(uint256 tokenId) public view returns (bool) { diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index e0557ddbf..e2d170101 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -198,7 +198,7 @@ contract ERC721 is ERC165, IERC721 { * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to The address that will own the minted token - * @param tokenId uint256 ID of the token to be minted by the msg.sender + * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); @@ -209,7 +209,9 @@ contract ERC721 is ERC165, IERC721 { /** * @dev Internal function to burn a specific token * Reverts if the token does not exist - * @param tokenId uint256 ID of the token being burned by the msg.sender + * Deprecated, use _burn(uint256) instead. + * @param owner owner of the token to burn + * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { _clearApproval(tokenId); @@ -217,6 +219,15 @@ contract ERC721 is ERC165, IERC721 { emit Transfer(owner, address(0), tokenId); } + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param tokenId uint256 ID of the token being burned + */ + function _burn(uint256 tokenId) internal { + _burn(ownerOf(tokenId), tokenId); + } + /** * @dev Internal function to add a token ID to the list of a given address * Note that this function is left internal to make ERC721Enumerable possible, but is not diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index 2d8732b38..d8cb5e13f 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -13,6 +13,6 @@ contract ERC721Burnable is ERC721 { */ function burn(uint256 tokenId) public { require(_isApprovedOrOwner(msg.sender, tokenId)); - _burn(ownerOf(tokenId), tokenId); + _burn(tokenId); } } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index 441624c02..cf7464ea7 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -117,7 +117,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to address the beneficiary that will own the minted token - * @param tokenId uint256 ID of the token to be minted by the msg.sender + * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { super._mint(to, tokenId); @@ -129,8 +129,9 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { /** * @dev Internal function to burn a specific token * Reverts if the token does not exist + * Deprecated, use _burn(uint256) instead * @param owner owner of the token to burn - * @param tokenId uint256 ID of the token being burned by the msg.sender + * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); @@ -147,10 +148,10 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { _allTokensIndex[tokenId] = 0; _allTokensIndex[lastToken] = tokenIndex; } - + /** * @dev Gets the list of token IDs of the requested owner - * @param owner address owning the tokens + * @param owner address owning the tokens * @return uint256[] List of token IDs owned by the requested address */ function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 522b626e8..df0379294 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -73,6 +73,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { /** * @dev Internal function to burn a specific token * Reverts if the token does not exist + * Deprecated, use _burn(uint256) instead * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned by the msg.sender */ From 7142e25e78268731982f5658e9e47dfe373222f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 12 Dec 2018 14:46:07 -0300 Subject: [PATCH 183/205] Add back WhitelistedCrowdsale (#1525) * Added WhitelisterRole. * Added WhitelisteeRole and WhitelistedCrowdsale. * Added WhitelistedCrowdsale tests. * Whitelisters can now remove Whitelistees. * PublicRole.behavior now supports a manager account, added Whitelistee tests. * Rephrased tests, added test for whitelistees doing invalid purchases. * Fixed linter error. * Fixed typos Co-Authored-By: nventuro * Working around JS quirks Co-Authored-By: nventuro * Update PublicRole.behavior.js * Renamed WhitelisteeRole to WhitelistedRole. * Renamed WhitelistedCrowdsale to WhitelistCrowdsale. * Now using the new test helper. * Added basic documentation. --- contracts/access/roles/WhitelistedRole.sol | 50 +++++++++++++ contracts/access/roles/WhitelisterRole.sol | 47 ++++++++++++ .../validation/WhitelistCrowdsale.sol | 21 ++++++ contracts/mocks/WhitelistCrowdsaleImpl.sol | 10 +++ contracts/mocks/WhitelistedRoleMock.sol | 8 ++ contracts/mocks/WhitelisterRoleMock.sol | 17 +++++ test/access/roles/PublicRole.behavior.js | 75 +++++++++++-------- test/access/roles/WhitelistedRole.test.js | 12 +++ test/access/roles/WhitelisterRole.test.js | 11 +++ test/crowdsale/WhitelistCrowdsale.test.js | 57 ++++++++++++++ 10 files changed, 276 insertions(+), 32 deletions(-) create mode 100644 contracts/access/roles/WhitelistedRole.sol create mode 100644 contracts/access/roles/WhitelisterRole.sol create mode 100644 contracts/crowdsale/validation/WhitelistCrowdsale.sol create mode 100644 contracts/mocks/WhitelistCrowdsaleImpl.sol create mode 100644 contracts/mocks/WhitelistedRoleMock.sol create mode 100644 contracts/mocks/WhitelisterRoleMock.sol create mode 100644 test/access/roles/WhitelistedRole.test.js create mode 100644 test/access/roles/WhitelisterRole.test.js create mode 100644 test/crowdsale/WhitelistCrowdsale.test.js diff --git a/contracts/access/roles/WhitelistedRole.sol b/contracts/access/roles/WhitelistedRole.sol new file mode 100644 index 000000000..68a826197 --- /dev/null +++ b/contracts/access/roles/WhitelistedRole.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.4.24; + +import "../Roles.sol"; +import "./WhitelisterRole.sol"; + +/** + * @title WhitelistedRole + * @dev Whitelisted accounts have been approved by a Whitelister to perform certain actions (e.g. participate in a + * crowdsale). This role is special in that the only accounts that can add it are Whitelisters (who can also remove it), + * and not Whitelisteds themselves. + */ +contract WhitelistedRole is WhitelisterRole { + using Roles for Roles.Role; + + event WhitelistedAdded(address indexed account); + event WhitelistedRemoved(address indexed account); + + Roles.Role private _whitelisteds; + + modifier onlyWhitelisted() { + require(isWhitelisted(msg.sender)); + _; + } + + function isWhitelisted(address account) public view returns (bool) { + return _whitelisteds.has(account); + } + + function addWhitelisted(address account) public onlyWhitelister { + _addWhitelisted(account); + } + + function removeWhitelisted(address account) public onlyWhitelister { + _removeWhitelisted(account); + } + + function renounceWhitelisted() public { + _removeWhitelisted(msg.sender); + } + + function _addWhitelisted(address account) internal { + _whitelisteds.add(account); + emit WhitelistedAdded(account); + } + + function _removeWhitelisted(address account) internal { + _whitelisteds.remove(account); + emit WhitelistedRemoved(account); + } +} diff --git a/contracts/access/roles/WhitelisterRole.sol b/contracts/access/roles/WhitelisterRole.sol new file mode 100644 index 000000000..0abdeaaf7 --- /dev/null +++ b/contracts/access/roles/WhitelisterRole.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.24; + +import "../Roles.sol"; + +/** + * @title WhitelisterRole + * @dev Whitelisters are responsible for assigning and removing Whitelisted accounts. + */ +contract WhitelisterRole { + using Roles for Roles.Role; + + event WhitelisterAdded(address indexed account); + event WhitelisterRemoved(address indexed account); + + Roles.Role private _whitelisters; + + constructor () internal { + _addWhitelister(msg.sender); + } + + modifier onlyWhitelister() { + require(isWhitelister(msg.sender)); + _; + } + + function isWhitelister(address account) public view returns (bool) { + return _whitelisters.has(account); + } + + function addWhitelister(address account) public onlyWhitelister { + _addWhitelister(account); + } + + function renounceWhitelister() public { + _removeWhitelister(msg.sender); + } + + function _addWhitelister(address account) internal { + _whitelisters.add(account); + emit WhitelisterAdded(account); + } + + function _removeWhitelister(address account) internal { + _whitelisters.remove(account); + emit WhitelisterRemoved(account); + } +} diff --git a/contracts/crowdsale/validation/WhitelistCrowdsale.sol b/contracts/crowdsale/validation/WhitelistCrowdsale.sol new file mode 100644 index 000000000..d93028d59 --- /dev/null +++ b/contracts/crowdsale/validation/WhitelistCrowdsale.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.24; +import "../Crowdsale.sol"; +import "../../access/roles/WhitelistedRole.sol"; + + +/** + * @title WhitelistCrowdsale + * @dev Crowdsale in which only whitelisted users can contribute. + */ +contract WhitelistCrowdsale is WhitelistedRole, Crowdsale { + /** + * @dev Extend parent behavior requiring beneficiary to be whitelisted. Note that no + * restriction is imposed on the account sending the transaction. + * @param _beneficiary Token beneficiary + * @param _weiAmount Amount of wei contributed + */ + function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view { + require(isWhitelisted(_beneficiary)); + super._preValidatePurchase(_beneficiary, _weiAmount); + } +} diff --git a/contracts/mocks/WhitelistCrowdsaleImpl.sol b/contracts/mocks/WhitelistCrowdsaleImpl.sol new file mode 100644 index 000000000..ab8bd73fa --- /dev/null +++ b/contracts/mocks/WhitelistCrowdsaleImpl.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/IERC20.sol"; +import "../crowdsale/validation/WhitelistCrowdsale.sol"; +import "../crowdsale/Crowdsale.sol"; + + +contract WhitelistCrowdsaleImpl is Crowdsale, WhitelistCrowdsale { + constructor (uint256 _rate, address _wallet, IERC20 _token) Crowdsale(_rate, _wallet, _token) public {} +} diff --git a/contracts/mocks/WhitelistedRoleMock.sol b/contracts/mocks/WhitelistedRoleMock.sol new file mode 100644 index 000000000..b710c38d4 --- /dev/null +++ b/contracts/mocks/WhitelistedRoleMock.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.24; + +import "../access/roles/WhitelistedRole.sol"; + +contract WhitelistedRoleMock is WhitelistedRole { + function onlyWhitelistedMock() public view onlyWhitelisted { + } +} diff --git a/contracts/mocks/WhitelisterRoleMock.sol b/contracts/mocks/WhitelisterRoleMock.sol new file mode 100644 index 000000000..06ea7dd63 --- /dev/null +++ b/contracts/mocks/WhitelisterRoleMock.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.4.24; + +import "../access/roles/WhitelisterRole.sol"; + +contract WhitelisterRoleMock is WhitelisterRole { + function removeWhitelister(address account) public { + _removeWhitelister(account); + } + + function onlyWhitelisterMock() public view onlyWhitelister { + } + + // Causes a compilation error if super._removeWhitelister is not internal + function _removeWhitelister(address account) internal { + super._removeWhitelister(account); + } +} diff --git a/test/access/roles/PublicRole.behavior.js b/test/access/roles/PublicRole.behavior.js index c18b60974..d558c1300 100644 --- a/test/access/roles/PublicRole.behavior.js +++ b/test/access/roles/PublicRole.behavior.js @@ -8,7 +8,7 @@ function capitalize (str) { return str.replace(/\b\w/g, l => l.toUpperCase()); } -function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename) { +function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename, manager) { rolename = capitalize(rolename); describe('should behave like public role', function () { @@ -18,11 +18,13 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role (await this.contract[`is${rolename}`](anyone)).should.equal(false); }); - it('emits events during construction', async function () { - await expectEvent.inConstruction(this.contract, `${rolename}Added`, { - account: authorized, + if (manager === undefined) { // Managed roles are only assigned by the manager, and none are set at construction + it('emits events during construction', async function () { + await expectEvent.inConstruction(this.contract, `${rolename}Added`, { + account: authorized, + }); }); - }); + } it('reverts when querying roles for the null account', async function () { await shouldFail.reverting(this.contract[`is${rolename}`](ZERO_ADDRESS)); @@ -47,43 +49,52 @@ function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], role }); describe('add', function () { - it('adds role to a new account', async function () { - await this.contract[`add${rolename}`](anyone, { from: authorized }); - (await this.contract[`is${rolename}`](anyone)).should.equal(true); - }); + const from = manager === undefined ? authorized : manager; - it(`emits a ${rolename}Added event`, async function () { - const { logs } = await this.contract[`add${rolename}`](anyone, { from: authorized }); - expectEvent.inLogs(logs, `${rolename}Added`, { account: anyone }); - }); + context(`from ${manager ? 'the manager' : 'a role-haver'} account`, function () { + it('adds role to a new account', async function () { + await this.contract[`add${rolename}`](anyone, { from }); + (await this.contract[`is${rolename}`](anyone)).should.equal(true); + }); - it('reverts when adding role to an already assigned account', async function () { - await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from: authorized })); - }); + it(`emits a ${rolename}Added event`, async function () { + const { logs } = await this.contract[`add${rolename}`](anyone, { from }); + expectEvent.inLogs(logs, `${rolename}Added`, { account: anyone }); + }); - it('reverts when adding role to the null account', async function () { - await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized })); + it('reverts when adding role to an already assigned account', async function () { + await shouldFail.reverting(this.contract[`add${rolename}`](authorized, { from })); + }); + + it('reverts when adding role to the null account', async function () { + await shouldFail.reverting(this.contract[`add${rolename}`](ZERO_ADDRESS, { from })); + }); }); }); describe('remove', function () { - it('removes role from an already assigned account', async function () { - await this.contract[`remove${rolename}`](authorized); - (await this.contract[`is${rolename}`](authorized)).should.equal(false); - (await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true); - }); + // Non-managed roles have no restrictions on the mocked '_remove' function (exposed via 'remove'). + const from = manager || anyone; - it(`emits a ${rolename}Removed event`, async function () { - const { logs } = await this.contract[`remove${rolename}`](authorized); - expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); - }); + context(`from ${manager ? 'the manager' : 'any'} account`, function () { + it('removes role from an already assigned account', async function () { + await this.contract[`remove${rolename}`](authorized, { from }); + (await this.contract[`is${rolename}`](authorized)).should.equal(false); + (await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true); + }); - it('reverts when removing from an unassigned account', async function () { - await shouldFail.reverting(this.contract[`remove${rolename}`](anyone)); - }); + it(`emits a ${rolename}Removed event`, async function () { + const { logs } = await this.contract[`remove${rolename}`](authorized, { from }); + expectEvent.inLogs(logs, `${rolename}Removed`, { account: authorized }); + }); - it('reverts when removing role from the null account', async function () { - await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS)); + it('reverts when removing from an unassigned account', async function () { + await shouldFail.reverting(this.contract[`remove${rolename}`](anyone), { from }); + }); + + it('reverts when removing role from the null account', async function () { + await shouldFail.reverting(this.contract[`remove${rolename}`](ZERO_ADDRESS), { from }); + }); }); }); diff --git a/test/access/roles/WhitelistedRole.test.js b/test/access/roles/WhitelistedRole.test.js new file mode 100644 index 000000000..2290424cd --- /dev/null +++ b/test/access/roles/WhitelistedRole.test.js @@ -0,0 +1,12 @@ +const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); +const WhitelistedRoleMock = artifacts.require('WhitelistedRoleMock'); + +contract('WhitelistedRole', function ([_, whitelisted, otherWhitelisted, whitelister, ...otherAccounts]) { + beforeEach(async function () { + this.contract = await WhitelistedRoleMock.new({ from: whitelister }); + await this.contract.addWhitelisted(whitelisted, { from: whitelister }); + await this.contract.addWhitelisted(otherWhitelisted, { from: whitelister }); + }); + + shouldBehaveLikePublicRole(whitelisted, otherWhitelisted, otherAccounts, 'whitelisted', whitelister); +}); diff --git a/test/access/roles/WhitelisterRole.test.js b/test/access/roles/WhitelisterRole.test.js new file mode 100644 index 000000000..39e664407 --- /dev/null +++ b/test/access/roles/WhitelisterRole.test.js @@ -0,0 +1,11 @@ +const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); +const WhitelisterRoleMock = artifacts.require('WhitelisterRoleMock'); + +contract('WhitelisterRole', function ([_, whitelister, otherWhitelister, ...otherAccounts]) { + beforeEach(async function () { + this.contract = await WhitelisterRoleMock.new({ from: whitelister }); + await this.contract.addWhitelister(otherWhitelister, { from: whitelister }); + }); + + shouldBehaveLikePublicRole(whitelister, otherWhitelister, otherAccounts, 'whitelister'); +}); diff --git a/test/crowdsale/WhitelistCrowdsale.test.js b/test/crowdsale/WhitelistCrowdsale.test.js new file mode 100644 index 000000000..713de675e --- /dev/null +++ b/test/crowdsale/WhitelistCrowdsale.test.js @@ -0,0 +1,57 @@ +require('../helpers/setup'); +const { ether } = require('../helpers/ether'); +const shouldFail = require('../helpers/shouldFail'); + +const BigNumber = web3.BigNumber; + +const WhitelistCrowdsale = artifacts.require('WhitelistCrowdsaleImpl'); +const SimpleToken = artifacts.require('SimpleToken'); + +contract('WhitelistCrowdsale', function ([_, wallet, whitelister, whitelisted, otherWhitelisted, anyone]) { + const rate = 1; + const value = ether(42); + const tokenSupply = new BigNumber('1e22'); + + beforeEach(async function () { + this.token = await SimpleToken.new({ from: whitelister }); + this.crowdsale = await WhitelistCrowdsale.new(rate, wallet, this.token.address, { from: whitelister }); + await this.token.transfer(this.crowdsale.address, tokenSupply, { from: whitelister }); + }); + + async function purchaseShouldSucceed (crowdsale, beneficiary, value) { + await crowdsale.buyTokens(beneficiary, { from: beneficiary, value }); + await crowdsale.sendTransaction({ from: beneficiary, value }); + } + + async function purchaseShouldFail (crowdsale, beneficiary, value) { + await shouldFail.reverting(crowdsale.buyTokens(beneficiary, { from: beneficiary, value })); + await shouldFail.reverting(crowdsale.sendTransaction({ from: beneficiary, value })); + } + + context('with no whitelisted addresses', function () { + it('rejects all purchases', async function () { + await purchaseShouldFail(this.crowdsale, anyone, value); + await purchaseShouldFail(this.crowdsale, whitelisted, value); + }); + }); + + context('with whitelisted addresses', function () { + beforeEach(async function () { + await this.crowdsale.addWhitelisted(whitelisted, { from: whitelister }); + await this.crowdsale.addWhitelisted(otherWhitelisted, { from: whitelister }); + }); + + it('accepts purchases with whitelisted beneficiaries', async function () { + await purchaseShouldSucceed(this.crowdsale, whitelisted, value); + await purchaseShouldSucceed(this.crowdsale, otherWhitelisted, value); + }); + + it('rejects purchases from whitelisted addresses with non-whitelisted beneficiaries', async function () { + await shouldFail(this.crowdsale.buyTokens(anyone, { from: whitelisted, value })); + }); + + it('rejects purchases with non-whitelisted beneficiaries', async function () { + await purchaseShouldFail(this.crowdsale, anyone, value); + }); + }); +}); From a99b9da3d41cef7126c60279c70e3f9ce8cd21a6 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 12 Dec 2018 15:36:00 -0300 Subject: [PATCH 184/205] Automate build step (#1551) * remove note that was fixed in #1526 * add build script * add prepack script * remove custom compilation steps --- RELEASING.md | 16 ++-------------- package.json | 4 +++- scripts/build.sh | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) create mode 100755 scripts/build.sh diff --git a/RELEASING.md b/RELEASING.md index 7ef7f098f..20f1132ad 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -34,13 +34,7 @@ git push upstream vX.Y.Z-rc.R Draft the release notes in our [GitHub releases](https://github.com/OpenZeppelin/openzeppelin-solidity/releases). Make sure to mark it as a pre-release! Try to be consistent with our previous release notes in the title and format of the text. Release candidates don't need a detailed changelog, but make sure to include a link to GitHub's compare page. -Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. - -1. Delete the `contracts/mocks`, `contracts/examples` and `build` directories. -2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) -3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. - -Once the CI run for the new tag is green, publish on npm under the `next` tag. +Once the CI run for the new tag is green, publish on npm under the `next` tag. You should see the contracts compile automatically. ``` npm publish --tag next @@ -68,13 +62,7 @@ git push upstream vX.Y.Z Draft the release notes in GitHub releases. Try to be consistent with our previous release notes in the title and format of the text. Make sure to include a detailed changelog. -Before publishing on npm you need to generate the build artifacts. This is not done automatically at the moment because of a bug in Truffle. Since some of the contracts should not be included in the package, this is a _hairy_ process that you need to do with care. - -1. Delete the `contracts/mocks`, `contracts/examples` and `build` directories. -2. Run `truffle compile`. (Note that the Truffle process may never exit and you will have to interrupt it.) -3. Recover the directories using `git checkout`. It doesn't matter if you do this now or later. - -Once the CI run for the new tag is green, publish on npm. +Once the CI run for the new tag is green, publish on npm. You should see the contracts compile automatically. ``` npm publish diff --git a/package.json b/package.json index fa030dfc5..f4b6b0fbc 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", "console": "truffle console", "coverage": "scripts/coverage.sh", - "version": "scripts/version.js" + "version": "scripts/version.js", + "build": "scripts/build.sh", + "prepack": "npm run build" }, "repository": { "type": "git", diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 000000000..f48b92d06 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Configure to exit script as soon as a command fails. +set -o errexit + +# Clean the existing build directory. +rm -rf build + +# Create a temporary directory to place ignored files (e.g. examples). +tmp_dir="$(mktemp -dp.)" + +# Move the ignored files to the temporary directory. +while IFS="" read -r ignored +do + mv "contracts/$ignored" "$tmp_dir" +done < contracts/.npmignore + +# Compile everything else. +node_modules/.bin/truffle compile + +# Return ignored files to their place. +mv "$tmp_dir/"* contracts/ + +# Delete the temporary directory. +rmdir "$tmp_dir" From 2da19eebd330c0309284ab9f762f4f7c75af36b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 12 Dec 2018 17:38:26 -0300 Subject: [PATCH 185/205] Update Arrays.sol to require solc 0.4.24. (#1553) --- contracts/utils/Arrays.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol index 7d8e29339..67f6a784e 100644 --- a/contracts/utils/Arrays.sol +++ b/contracts/utils/Arrays.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.23; +pragma solidity ^0.4.24; import "../math/Math.sol"; From 12533bcb2b69a680d4cd0562de3954d041f1e6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 12 Dec 2018 18:51:43 -0300 Subject: [PATCH 186/205] ERC721 bugfix + gas optimizations (#1549) * Now only swapping when needed. * Removed _addTokenTo and _removeTokenFrom * Removed removeTokenFrom test. * Added tests for ERC721 _mint and _burn * _burn now uses the same swap and pop mechanism as _removeFromOwner * Gas optimization on burn --- contracts/mocks/ERC721FullMock.sol | 6 +- contracts/mocks/ERC721Mock.sol | 4 + contracts/token/ERC721/ERC721.sol | 42 +++----- contracts/token/ERC721/ERC721Enumerable.sol | 104 +++++++++---------- test/token/ERC721/ERC721.test.js | 107 +++++++++++++++++++- test/token/ERC721/ERC721Full.test.js | 31 ------ 6 files changed, 170 insertions(+), 124 deletions(-) diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index 669997557..d917e8f63 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -8,7 +8,7 @@ import "../token/ERC721/ERC721Burnable.sol"; /** * @title ERC721FullMock * This mock just provides public functions for setting metadata URI, getting all tokens of an owner, - * checking token existence, removal of a token from an address + * checking token existence, removal of a token from an address */ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { constructor (string name, string symbol) public ERC721Mintable() ERC721Full(name, symbol) {} @@ -24,8 +24,4 @@ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, E function setTokenURI(uint256 tokenId, string uri) public { _setTokenURI(tokenId, uri); } - - function removeTokenFrom(address from, uint256 tokenId) public { - _removeTokenFrom(from, tokenId); - } } diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index 2a429fbae..f953d944d 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -11,6 +11,10 @@ contract ERC721Mock is ERC721 { _mint(to, tokenId); } + function burn(address owner, uint256 tokenId) public { + _burn(owner, tokenId); + } + function burn(uint256 tokenId) public { _burn(tokenId); } diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index e2d170101..007f6e580 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -202,7 +202,11 @@ contract ERC721 is ERC165, IERC721 { */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); - _addTokenTo(to, tokenId); + require(!_exists(tokenId)); + + _tokenOwner[tokenId] = to; + _ownedTokensCount[to] = _ownedTokensCount[to].add(1); + emit Transfer(address(0), to, tokenId); } @@ -214,11 +218,16 @@ contract ERC721 is ERC165, IERC721 { * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { + require(ownerOf(tokenId) == owner); + _clearApproval(tokenId); - _removeTokenFrom(owner, tokenId); + + _ownedTokensCount[owner] = _ownedTokensCount[owner].sub(1); + _tokenOwner[tokenId] = address(0); + emit Transfer(owner, address(0), tokenId); } - + /** * @dev Internal function to burn a specific token * Reverts if the token does not exist @@ -228,33 +237,6 @@ contract ERC721 is ERC165, IERC721 { _burn(ownerOf(tokenId), tokenId); } - /** - * @dev Internal function to add a token ID to the list of a given address - * Note that this function is left internal to make ERC721Enumerable possible, but is not - * intended to be called by custom derived contracts: in particular, it emits no Transfer event. - * @param to address representing the new owner of the given token ID - * @param tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function _addTokenTo(address to, uint256 tokenId) internal { - require(_tokenOwner[tokenId] == address(0)); - _tokenOwner[tokenId] = to; - _ownedTokensCount[to] = _ownedTokensCount[to].add(1); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * Note that this function is left internal to make ERC721Enumerable possible, but is not - * intended to be called by custom derived contracts: in particular, it emits no Transfer event, - * and doesn't clear approvals. - * @param from address representing the previous owner of the given token ID - * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function _removeTokenFrom(address from, uint256 tokenId) internal { - require(ownerOf(tokenId) == from); - _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); - _tokenOwner[tokenId] = address(0); - } - /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index cf7464ea7..a543c75f7 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -67,37 +67,6 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { return _allTokens[index]; } - /** - * @dev Internal function to add a token ID to the list of a given address - * This function is internal due to language limitations, see the note in ERC721.sol. - * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event. - * @param to address representing the new owner of the given token ID - * @param tokenId uint256 ID of the token to be added to the tokens list of the given address - */ - function _addTokenTo(address to, uint256 tokenId) internal { - super._addTokenTo(to, tokenId); - - _addTokenToOwnerEnumeration(to, tokenId); - } - - /** - * @dev Internal function to remove a token ID from the list of a given address - * This function is internal due to language limitations, see the note in ERC721.sol. - * It is not intended to be called by custom derived contracts: in particular, it emits no Transfer event, - * and doesn't clear approvals. - * @param from address representing the previous owner of the given token ID - * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address - */ - function _removeTokenFrom(address from, uint256 tokenId) internal { - super._removeTokenFrom(from, tokenId); - - _removeTokenFromOwnerEnumeration(from, tokenId); - - // Since the token is being destroyed, we also clear its index - // TODO(nventuro): 0 is still a valid index, so arguably this isnt really helpful, remove? - _ownedTokensIndex[tokenId] = 0; - } - /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. @@ -122,8 +91,9 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { function _mint(address to, uint256 tokenId) internal { super._mint(to, tokenId); - _allTokensIndex[tokenId] = _allTokens.length; - _allTokens.push(tokenId); + _addTokenToOwnerEnumeration(to, tokenId); + + _addTokenToAllTokensEnumeration(tokenId); } /** @@ -136,17 +106,11 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); - // Reorg all tokens array - uint256 tokenIndex = _allTokensIndex[tokenId]; - uint256 lastTokenIndex = _allTokens.length.sub(1); - uint256 lastToken = _allTokens[lastTokenIndex]; + _removeTokenFromOwnerEnumeration(owner, tokenId); + // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund + _ownedTokensIndex[tokenId] = 0; - _allTokens[tokenIndex] = lastToken; - _allTokens[lastTokenIndex] = 0; - - _allTokens.length--; - _allTokensIndex[tokenId] = 0; - _allTokensIndex[lastToken] = tokenIndex; + _removeTokenFromAllTokensEnumeration(tokenId); } /** @@ -164,9 +128,17 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { - uint256 newOwnedTokensLength = _ownedTokens[to].push(tokenId); - // No need to use SafeMath since the length after a push cannot be zero - _ownedTokensIndex[tokenId] = newOwnedTokensLength - 1; + _ownedTokensIndex[tokenId] = _ownedTokens[to].length; + _ownedTokens[to].push(tokenId); + } + + /** + * @dev Private function to add a token to this extension's token tracking data structures. + * @param tokenId uint256 ID of the token to be added to the tokens list + */ + function _addTokenToAllTokensEnumeration(uint256 tokenId) private { + _allTokensIndex[tokenId] = _allTokens.length; + _allTokens.push(tokenId); } /** @@ -182,21 +154,45 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // then delete the last slot (swap and pop). uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); - uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; - uint256 tokenIndex = _ownedTokensIndex[tokenId]; - _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token - _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + // When the token to delete is the last token, the swap operation is unnecessary + if (tokenIndex != lastTokenIndex) { + uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; - // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going - // to be zero. The swap operation will therefore have no effect, but the token _will_ be deleted during the - // 'pop' operation. + _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token + _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + } // This also deletes the contents at the last position of the array _ownedTokens[from].length--; // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occcupied by - // lasTokenId). + // lasTokenId, or just over the end of the array if the token was the last one). + } + + /** + * @dev Private function to remove a token from this extension's token tracking data structures. + * This has O(1) time complexity, but alters the order of the _allTokens array. + * @param tokenId uint256 ID of the token to be removed from the tokens list + */ + function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { + // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and + // then delete the last slot (swap and pop). + + uint256 lastTokenIndex = _allTokens.length.sub(1); + uint256 tokenIndex = _allTokensIndex[tokenId]; + + // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so + // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding + // an 'if' statement (like in _removeTokenFromOwnerEnumeration) + uint256 lastTokenId = _allTokens[lastTokenIndex]; + + _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token + _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index + + // This also deletes the contents at the last position of the array + _allTokens.length--; + _allTokensIndex[tokenId] = 0; } } diff --git a/test/token/ERC721/ERC721.test.js b/test/token/ERC721/ERC721.test.js index 87e895f14..8ae1c05eb 100644 --- a/test/token/ERC721/ERC721.test.js +++ b/test/token/ERC721/ERC721.test.js @@ -1,13 +1,112 @@ -const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); +require('../../helpers/setup'); +const { ZERO_ADDRESS } = require('../../helpers/constants'); +const expectEvent = require('../../helpers/expectEvent'); +const send = require('../../helpers/send'); +const shouldFail = require('../../helpers/shouldFail'); +const { shouldBehaveLikeERC721 } = require('./ERC721.behavior'); const ERC721Mock = artifacts.require('ERC721Mock.sol'); -require('../../helpers/setup'); - -contract('ERC721', function ([_, creator, ...accounts]) { +contract('ERC721', function ([_, creator, tokenOwner, anyone, ...accounts]) { beforeEach(async function () { this.token = await ERC721Mock.new({ from: creator }); }); shouldBehaveLikeERC721(creator, creator, accounts); + + describe('internal functions', function () { + const tokenId = 5042; + + describe('_mint(address, uint256)', function () { + it('reverts with a null destination address', async function () { + await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, tokenId)); + }); + + context('with minted token', async function () { + beforeEach(async function () { + ({ logs: this.logs } = await this.token.mint(tokenOwner, tokenId)); + }); + + it('emits a Transfer event', function () { + expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: tokenOwner, tokenId }); + }); + + it('creates the token', async function () { + (await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(1); + (await this.token.ownerOf(tokenId)).should.equal(tokenOwner); + }); + + it('reverts when adding a token id that already exists', async function () { + await shouldFail.reverting(this.token.mint(tokenOwner, tokenId)); + }); + }); + }); + + describe('_burn(address, uint256)', function () { + it('reverts when burning a non-existent token id', async function () { + await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId])); + }); + + context('with minted token', function () { + beforeEach(async function () { + await this.token.mint(tokenOwner, tokenId); + }); + + it('reverts when the account is not the owner', async function () { + await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [anyone, tokenId])); + }); + + context('with burnt token', function () { + beforeEach(async function () { + ({ logs: this.logs } = + await send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId])); + }); + + it('emits a Transfer event', function () { + expectEvent.inLogs(this.logs, 'Transfer', { from: tokenOwner, to: ZERO_ADDRESS, tokenId }); + }); + + it('deletes the token', async function () { + (await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(0); + await shouldFail.reverting(this.token.ownerOf(tokenId)); + }); + + it('reverts when burning a token id that has been deleted', async function () { + await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId])); + }); + }); + }); + }); + + describe('_burn(uint256)', function () { + it('reverts when burning a non-existent token id', async function () { + await shouldFail.reverting(send.transaction(this.token, 'burn', 'uint256', [tokenId])); + }); + + context('with minted token', function () { + beforeEach(async function () { + await this.token.mint(tokenOwner, tokenId); + }); + + context('with burnt token', function () { + beforeEach(async function () { + ({ logs: this.logs } = await send.transaction(this.token, 'burn', 'uint256', [tokenId])); + }); + + it('emits a Transfer event', function () { + expectEvent.inLogs(this.logs, 'Transfer', { from: tokenOwner, to: ZERO_ADDRESS, tokenId }); + }); + + it('deletes the token', async function () { + (await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(0); + await shouldFail.reverting(this.token.ownerOf(tokenId)); + }); + + it('reverts when burning a token id that has been deleted', async function () { + await shouldFail.reverting(send.transaction(this.token, 'burn', 'uint256', [tokenId])); + }); + }); + }); + }); + }); }); diff --git a/test/token/ERC721/ERC721Full.test.js b/test/token/ERC721/ERC721Full.test.js index 3870a95f6..a7642184f 100644 --- a/test/token/ERC721/ERC721Full.test.js +++ b/test/token/ERC721/ERC721Full.test.js @@ -23,7 +23,6 @@ contract('ERC721Full', function ([ owner, newOwner, another, - anyone, ] = accounts; beforeEach(async function () { @@ -70,36 +69,6 @@ contract('ERC721Full', function ([ }); }); - describe('removeTokenFrom', function () { - it('reverts if the correct owner is not passed', async function () { - await shouldFail.reverting( - this.token.removeTokenFrom(anyone, firstTokenId, { from: owner }) - ); - }); - - context('once removed', function () { - beforeEach(async function () { - await this.token.removeTokenFrom(owner, firstTokenId, { from: owner }); - }); - - it('has been removed', async function () { - await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 1)); - }); - - it('adjusts token list', async function () { - (await this.token.tokenOfOwnerByIndex(owner, 0)).toNumber().should.be.equal(secondTokenId); - }); - - it('adjusts owner count', async function () { - (await this.token.balanceOf(owner)).toNumber().should.be.equal(1); - }); - - it('does not adjust supply', async function () { - (await this.token.totalSupply()).toNumber().should.be.equal(2); - }); - }); - }); - describe('metadata', function () { const sampleUri = 'mock://mytoken'; From 8056433c44d40173127798345e308333e98b7fce Mon Sep 17 00:00:00 2001 From: Tal Ater Date: Fri, 14 Dec 2018 17:35:38 +0200 Subject: [PATCH 187/205] Added PausableCrowdsale contract (#832) * Added PausableCrowdsale contract * Changed inheritance order to prevent "Linearization of inheritance graph impossible" error * Updated mock PausableCrowdsaleImpl to new constructor syntax * Broke function definition to multiple lines Comply with new max line length * Rename events to past-tense in PausableCrowdsale test * Removed should.be.fullfilled from PausableCrowdsale tests * Change import assertRevert to require in PausableCrowdsale tests * Remove dependency on chai-as-promised and added BigNumber support in PausableCrowdsale tests * reindent solidity with 4 spaces * add missing view modifier in _preValidatePurchase * convert assertRevert to new shoulFail helper * add new setup helper * use expectEvent * convert to assert to chai should style * add description to beforeEach blocks * extract common step to beforeEach * improve documentation * revert inheritance error * move PausableCrowdsale into crowdsale/validation * make documentation more specific * put whitespace in line with convention * improve test suite account names * undo beforeEach descriptions * simplify tests * fix transaction senders to be the anyone account * make transaction senders more explicit * remove mocha only --- .../validation/PausableCrowdsale.sol | 22 +++++++++ contracts/mocks/PausableCrowdsaleImpl.sol | 9 ++++ test/crowdsale/PausableCrowdsale.test.js | 46 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 contracts/crowdsale/validation/PausableCrowdsale.sol create mode 100644 contracts/mocks/PausableCrowdsaleImpl.sol create mode 100644 test/crowdsale/PausableCrowdsale.test.js diff --git a/contracts/crowdsale/validation/PausableCrowdsale.sol b/contracts/crowdsale/validation/PausableCrowdsale.sol new file mode 100644 index 000000000..65fb0019f --- /dev/null +++ b/contracts/crowdsale/validation/PausableCrowdsale.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.4.18; + +import "../Crowdsale.sol"; +import "../../lifecycle/Pausable.sol"; + + +/** + * @title PausableCrowdsale + * @dev Extension of Crowdsale contract where purchases can be paused and unpaused by the pauser role. + */ +contract PausableCrowdsale is Crowdsale, Pausable { + + /** + * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations. + * Adds the validation that the crowdsale must not be paused. + * @param _beneficiary Address performing the token purchase + * @param _weiAmount Value in wei involved in the purchase + */ + function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view whenNotPaused { + return super._preValidatePurchase(_beneficiary, _weiAmount); + } +} diff --git a/contracts/mocks/PausableCrowdsaleImpl.sol b/contracts/mocks/PausableCrowdsaleImpl.sol new file mode 100644 index 000000000..64b4bc578 --- /dev/null +++ b/contracts/mocks/PausableCrowdsaleImpl.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.18; + +import "../token/ERC20/ERC20.sol"; +import "../crowdsale/validation/PausableCrowdsale.sol"; + +contract PausableCrowdsaleImpl is PausableCrowdsale { + constructor (uint256 _rate, address _wallet, ERC20 _token) public Crowdsale(_rate, _wallet, _token) { + } +} diff --git a/test/crowdsale/PausableCrowdsale.test.js b/test/crowdsale/PausableCrowdsale.test.js new file mode 100644 index 000000000..2d0d0513d --- /dev/null +++ b/test/crowdsale/PausableCrowdsale.test.js @@ -0,0 +1,46 @@ +const shouldFail = require('../helpers/shouldFail'); + +const PausableCrowdsale = artifacts.require('PausableCrowdsaleImpl'); +const SimpleToken = artifacts.require('SimpleToken'); + +require('../helpers/setup'); + +contract('PausableCrowdsale', function ([_, pauser, wallet, anyone]) { + const rate = 1; + const value = 1; + + beforeEach(async function () { + const from = pauser; + + this.token = await SimpleToken.new({ from }); + this.crowdsale = await PausableCrowdsale.new(rate, wallet, this.token.address, { from }); + await this.token.transfer(this.crowdsale.address, 2 * value, { from }); + }); + + it('purchases work', async function () { + await this.crowdsale.sendTransaction({ from: anyone, value }); + await this.crowdsale.buyTokens(anyone, { from: anyone, value }); + }); + + context('after pause', function () { + beforeEach(async function () { + await this.crowdsale.pause({ from: pauser }); + }); + + it('purchases do not work', async function () { + await shouldFail.reverting(this.crowdsale.sendTransaction({ from: anyone, value })); + await shouldFail.reverting(this.crowdsale.buyTokens(anyone, { from: anyone, value })); + }); + + context('after unpause', function () { + beforeEach(async function () { + await this.crowdsale.unpause({ from: pauser }); + }); + + it('purchases work', async function () { + await this.crowdsale.sendTransaction({ from: anyone, value }); + await this.crowdsale.buyTokens(anyone, { from: anyone, value }); + }); + }); + }); +}); From fad30c3d2c01b0052a560fbefbc310dc4c913a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 18 Dec 2018 14:26:23 -0300 Subject: [PATCH 188/205] Added changelog. (#1555) * Added changelog. * Added PR template note. * Update .github/PULL_REQUEST_TEMPLATE.md Co-Authored-By: nventuro * Update PULL_REQUEST_TEMPLATE.md * Update CHANGELOG.md Co-Authored-By: nventuro * Update CHANGELOG.md Co-Authored-By: nventuro * Apply suggestions from code review Co-Authored-By: nventuro * Added more headers and sub-headers. * Added deprecations category. * Added PR links. * Added PausableCrowdsale. * Addressed review comments. * Update CHANGELOG.md Co-Authored-By: nventuro --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++-- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2d743d0fe..7ffea25e9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,6 +15,7 @@ Fixes # - reviewed the OpenZeppelin Contributor Guidelines (https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md), - added tests where applicable to test new functionality, - - made sure that your contracts are well-documented, and - - run the JS/Solidity linters and fixed any issues (`npm run lint:fix`). + - made sure that your contracts are well-documented, + - run the JS/Solidity linters and fixed any issues (`npm run lint:fix`), and + - updated the changelog, if applicable. --> diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..088245ffa --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +## 2.1.0 (unreleased) + +### New features: + * `WhitelistCrowdsale`: a crowdsale where only whitelisted accounts (`WhitelistedRole`) can purchase tokens. Adding or removing accounts from the whitelist is done by whitelisters (`WhitelisterRole`). Similar to the pre-2.0 `WhitelistedCrowdsale`. ([#1525](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1525)) + * `RefundablePostDeliveryCrowdsale`: replacement for `RefundableCrowdsale` (deprecated, see below) where tokens are only granted once the crowdsale ends (if it meets its goal). ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543)) + * `PausableCrowdsale`: allows for pausers (`PauserRole`) to pause token purchases. Other crowdsale operations (e.g. withdrawals and refunds, if applicable) are not affected. ([#832](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/832)) + * `ERC20`: `transferFrom` and `_burnFrom ` now emit `Approval` events, to represent the token's state comprehensively through events. ([#1524](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1524)) + * `ERC721`: added `_burn(uint256 tokenId)`, replacing the similar deprecated function (see below). ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550)) + * `ERC721`: added `_tokensOfOwner(address owner)`, allowing to internally retrieve the array of an account's owned tokens. ([#1522](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1522)) + +### Improvements: + * The compiler version required by `Array` was behind the rest of the libray so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553)) + * Now conforming to a 4-space indentation code style. ([1508](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1508)) + * `ERC20`: more gas efficient due to removed redundant `require`s. ([#1409](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1409)) + * `ERC721`: fixed a bug that prevented internal data structures from being properly cleaned, missing potential gas refunds. ([#1539](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1539) and [#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549)) + * `ERC721`: general gas savings on `transferFrom`, `_mint` and `_burn`, due to redudant `require`s and `SSTORE`s. ([#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549)) + +### Bugfixes: + +### Breaking changes: + +### Deprecations: + * `ERC721._burn(address owner, uint256 tokenId)`: due to the `owner` parameter being unnecessary. ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550)) + * `RefundableCrowdsale`: due to trading abuse potential on crowdsales that miss their goal. ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543)) From d17ae0b806b2f8e69b291284bbf30321640609e3 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 18 Dec 2018 15:54:44 -0300 Subject: [PATCH 189/205] Signed SafeMath (#1559) * signed safe math * fix lint errors * refactor overflow checks and add descriptions * remove incorrect description * add test for reversed arguments in multiplication test * fix power operator * improve multiplication test descriptions * Update SafeMath.test.js * add feature to changelog --- CHANGELOG.md | 1 + contracts/math/SafeMath.sol | 63 +++++- contracts/mocks/SafeMathMock.sol | 28 ++- test/helpers/constants.js | 2 + test/math/SafeMath.test.js | 352 +++++++++++++++++++++---------- 5 files changed, 325 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 088245ffa..f63d7684f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * `ERC20`: `transferFrom` and `_burnFrom ` now emit `Approval` events, to represent the token's state comprehensively through events. ([#1524](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1524)) * `ERC721`: added `_burn(uint256 tokenId)`, replacing the similar deprecated function (see below). ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550)) * `ERC721`: added `_tokensOfOwner(address owner)`, allowing to internally retrieve the array of an account's owned tokens. ([#1522](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1522)) + * `SafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559)) ### Improvements: * The compiler version required by `Array` was behind the rest of the libray so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553)) diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index f42c48e25..777f62016 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -5,8 +5,10 @@ pragma solidity ^0.4.24; * @dev Math operations with safety checks that revert on error */ library SafeMath { + int256 constant private INT256_MIN = -2**255; + /** - * @dev Multiplies two numbers, reverts on overflow. + * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the @@ -23,7 +25,26 @@ library SafeMath { } /** - * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. + * @dev Multiplies two signed integers, reverts on overflow. + */ + function mul(int256 a, int256 b) internal pure returns (int256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below + + int256 c = a * b; + require(c / a == b); + + return c; + } + + /** + * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 @@ -35,7 +56,19 @@ library SafeMath { } /** - * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). + * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. + */ + function div(int256 a, int256 b) internal pure returns (int256) { + require(b != 0); // Solidity only automatically asserts when dividing by 0 + require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow + + int256 c = a / b; + + return c; + } + + /** + * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); @@ -45,7 +78,17 @@ library SafeMath { } /** - * @dev Adds two numbers, reverts on overflow. + * @dev Subtracts two signed integers, reverts on overflow. + */ + function sub(int256 a, int256 b) internal pure returns (int256) { + int256 c = a - b; + require((b >= 0 && c <= a) || (b < 0 && c > a)); + + return c; + } + + /** + * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; @@ -55,7 +98,17 @@ library SafeMath { } /** - * @dev Divides two numbers and returns the remainder (unsigned integer modulo), + * @dev Adds two signed integers, reverts on overflow. + */ + function add(int256 a, int256 b) internal pure returns (int256) { + int256 c = a + b; + require((b >= 0 && c >= a) || (b < 0 && c < a)); + + return c; + } + + /** + * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index 69ed0c38c..dba3e88c8 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -1,25 +1,43 @@ pragma solidity ^0.4.24; + import "../math/SafeMath.sol"; + contract SafeMathMock { - function mul(uint256 a, uint256 b) public pure returns (uint256) { + function mulUints(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.mul(a, b); } - function div(uint256 a, uint256 b) public pure returns (uint256) { + function mulInts(int256 a, int256 b) public pure returns (int256) { + return SafeMath.mul(a, b); + } + + function divUints(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.div(a, b); } - function sub(uint256 a, uint256 b) public pure returns (uint256) { + function divInts(int256 a, int256 b) public pure returns (int256) { + return SafeMath.div(a, b); + } + + function subUints(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.sub(a, b); } - function add(uint256 a, uint256 b) public pure returns (uint256) { + function subInts(int256 a, int256 b) public pure returns (int256) { + return SafeMath.sub(a, b); + } + + function addUints(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.add(a, b); } - function mod(uint256 a, uint256 b) public pure returns (uint256) { + function addInts(int256 a, int256 b) public pure returns (int256) { + return SafeMath.add(a, b); + } + + function modUints(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.mod(a, b); } } diff --git a/test/helpers/constants.js b/test/helpers/constants.js index 70d2242a3..4c75c6de2 100644 --- a/test/helpers/constants.js +++ b/test/helpers/constants.js @@ -3,4 +3,6 @@ const BigNumber = web3.BigNumber; module.exports = { ZERO_ADDRESS: '0x0000000000000000000000000000000000000000', MAX_UINT256: new BigNumber(2).pow(256).minus(1), + MAX_INT256: new BigNumber(2).pow(255).minus(1), + MIN_INT256: new BigNumber(2).pow(255).times(-1), }; diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index b006e06e1..e2cf371ef 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,5 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); -const { MAX_UINT256 } = require('../helpers/constants'); +const { MAX_UINT256, MIN_INT256, MAX_INT256 } = require('../helpers/constants'); const SafeMathMock = artifacts.require('SafeMathMock'); @@ -10,134 +10,264 @@ contract('SafeMath', function () { this.safeMath = await SafeMathMock.new(); }); - describe('add', function () { - it('adds correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(1234); + describe('unsigned', function () { + describe('add', function () { + it('adds correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); - (await this.safeMath.add(a, b)).should.be.bignumber.equal(a.plus(b)); - }); - - it('throws a revert error on addition overflow', async function () { - const a = MAX_UINT256; - const b = new BigNumber(1); - - await shouldFail.reverting(this.safeMath.add(a, b)); - }); - }); - - describe('sub', function () { - it('subtracts correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(1234); - - (await this.safeMath.sub(a, b)).should.be.bignumber.equal(a.minus(b)); - }); - - it('throws a revert error if subtraction result would be negative', async function () { - const a = new BigNumber(1234); - const b = new BigNumber(5678); - - await shouldFail.reverting(this.safeMath.sub(a, b)); - }); - }); - - describe('mul', function () { - it('multiplies correctly', async function () { - const a = new BigNumber(1234); - const b = new BigNumber(5678); - - (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); - }); - - it('handles a zero product correctly (first number as zero)', async function () { - const a = new BigNumber(0); - const b = new BigNumber(5678); - - (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); - }); - - it('handles a zero product correctly (second number as zero)', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); - - (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); - }); - - it('throws a revert error on multiplication overflow', async function () { - const a = MAX_UINT256; - const b = new BigNumber(2); - - await shouldFail.reverting(this.safeMath.mul(a, b)); - }); - }); - - describe('div', function () { - it('divides correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(5678); - - (await this.safeMath.div(a, b)).should.be.bignumber.equal(a.div(b)); - }); - - it('divides zero correctly', async function () { - const a = new BigNumber(0); - const b = new BigNumber(5678); - - (await this.safeMath.div(a, b)).should.be.bignumber.equal(0); - }); - - it('returns complete number result on non-even division', async function () { - const a = new BigNumber(7000); - const b = new BigNumber(5678); - - (await this.safeMath.div(a, b)).should.be.bignumber.equal(1); - }); - - it('throws a revert error on zero division', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); - - await shouldFail.reverting(this.safeMath.div(a, b)); - }); - }); - - describe('mod', function () { - describe('modulos correctly', async function () { - it('when the dividend is smaller than the divisor', async function () { - const a = new BigNumber(284); - const b = new BigNumber(5678); - - (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); + (await this.safeMath.addUints(a, b)).should.be.bignumber.equal(a.plus(b)); }); - it('when the dividend is equal to the divisor', async function () { + it('reverts on addition overflow', async function () { + const a = MAX_UINT256; + const b = new BigNumber(1); + + await shouldFail.reverting(this.safeMath.addUints(a, b)); + }); + }); + + describe('sub', function () { + it('subtracts correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); + + (await this.safeMath.subUints(a, b)).should.be.bignumber.equal(a.minus(b)); + }); + + it('reverts if subtraction result would be negative', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + await shouldFail.reverting(this.safeMath.subUints(a, b)); + }); + }); + + describe('mul', function () { + it('multiplies correctly', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); + }); + + it('handles a zero product correctly (first number as zero)', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); + }); + + it('handles a zero product correctly (second number as zero)', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); + + (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); + }); + + it('reverts on multiplication overflow', async function () { + const a = MAX_UINT256; + const b = new BigNumber(2); + + await shouldFail.reverting(this.safeMath.mulUints(a, b)); + }); + }); + + describe('div', function () { + it('divides correctly', async function () { const a = new BigNumber(5678); const b = new BigNumber(5678); - (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); + (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(a.div(b)); }); - it('when the dividend is larger than the divisor', async function () { + it('divides zero correctly', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(0); + }); + + it('returns complete number result on non-even division', async function () { const a = new BigNumber(7000); const b = new BigNumber(5678); - (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); + (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(1); }); - it('when the dividend is a multiple of the divisor', async function () { - const a = new BigNumber(17034); // 17034 == 5678 * 3 - const b = new BigNumber(5678); + it('reverts on zero division', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); - (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); + await shouldFail.reverting(this.safeMath.divUints(a, b)); }); }); - it('reverts with a 0 divisor', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); + describe('mod', function () { + describe('modulos correctly', async function () { + it('when the dividend is smaller than the divisor', async function () { + const a = new BigNumber(284); + const b = new BigNumber(5678); - await shouldFail.reverting(this.safeMath.mod(a, b)); + (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); + }); + + it('when the dividend is equal to the divisor', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(5678); + + (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); + }); + + it('when the dividend is larger than the divisor', async function () { + const a = new BigNumber(7000); + const b = new BigNumber(5678); + + (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); + }); + + it('when the dividend is a multiple of the divisor', async function () { + const a = new BigNumber(17034); // 17034 == 5678 * 3 + const b = new BigNumber(5678); + + (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); + }); + }); + + it('reverts with a 0 divisor', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); + + await shouldFail.reverting(this.safeMath.modUints(a, b)); + }); + }); + }); + + describe('signed', function () { + describe('add', function () { + it('adds correctly if it does not overflow and the result is positve', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + (await this.safeMath.addUints(a, b)).should.be.bignumber.equal(a.plus(b)); + }); + + it('adds correctly if it does not overflow and the result is negative', async function () { + const a = MAX_INT256; + const b = MIN_INT256; + + const result = await this.safeMath.addInts(a, b); + result.should.be.bignumber.equal(a.plus(b)); + }); + + it('reverts on positive addition overflow', async function () { + const a = MAX_INT256; + const b = new BigNumber(1); + + await shouldFail.reverting(this.safeMath.addInts(a, b)); + }); + + it('reverts on negative addition overflow', async function () { + const a = MIN_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.addInts(a, b)); + }); + }); + + describe('sub', function () { + it('subtracts correctly if it does not overflow and the result is positive', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); + + const result = await this.safeMath.subInts(a, b); + result.should.be.bignumber.equal(a.minus(b)); + }); + + it('subtracts correctly if it does not overflow and the result is negative', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + const result = await this.safeMath.subInts(a, b); + result.should.be.bignumber.equal(a.minus(b)); + }); + + it('reverts on positive subtraction overflow', async function () { + const a = MAX_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.subInts(a, b)); + }); + + it('reverts on negative subtraction overflow', async function () { + const a = MIN_INT256; + const b = new BigNumber(1); + + await shouldFail.reverting(this.safeMath.subInts(a, b)); + }); + }); + + describe('mul', function () { + it('multiplies correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(-1234); + + const result = await this.safeMath.mulInts(a, b); + result.should.be.bignumber.equal(a.times(b)); + }); + + it('handles a zero product correctly', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + const result = await this.safeMath.mulInts(a, b); + result.should.be.bignumber.equal(a.times(b)); + }); + + it('reverts on multiplication overflow, positive operands', async function () { + const a = MAX_INT256; + const b = new BigNumber(2); + + await shouldFail.reverting(this.safeMath.mulInts(a, b)); + }); + + it('reverts when minimum integer is multiplied by -1', async function () { + const a = MIN_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.mulInts(a, b)); + }); + + it('reverts when -1 is multiplied by minimum integer', async function () { + const a = new BigNumber(-1); + const b = MIN_INT256; + + await shouldFail.reverting(this.safeMath.mulInts(a, b)); + }); + }); + + describe('div', function () { + it('divides correctly', async function () { + const a = new BigNumber(-5678); + const b = new BigNumber(5678); + + const result = await this.safeMath.divInts(a, b); + result.should.be.bignumber.equal(a.div(b)); + }); + + it('reverts on zero division', async function () { + const a = new BigNumber(-5678); + const b = new BigNumber(0); + + await shouldFail.reverting(this.safeMath.divInts(a, b)); + }); + + it('reverts on overflow, negative second', async function () { + const a = new BigNumber(MIN_INT256); + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.divInts(a, b)); + }); }); }); }); From 54ceedbb1f811e2ac004569a329b559fb071c827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 18 Dec 2018 16:19:48 -0300 Subject: [PATCH 190/205] Made the Crowdsale's constructor public again. (#1564) * Made the Crowdsale's constructor public again. * Added changelog entry. * Made all but Finalizable public. --- CHANGELOG.md | 1 + contracts/crowdsale/Crowdsale.sol | 2 +- contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol | 2 -- contracts/crowdsale/distribution/RefundableCrowdsale.sol | 2 +- contracts/crowdsale/emission/AllowanceCrowdsale.sol | 2 +- contracts/crowdsale/emission/MintedCrowdsale.sol | 2 -- contracts/crowdsale/price/IncreasingPriceCrowdsale.sol | 2 +- contracts/crowdsale/validation/CappedCrowdsale.sol | 2 +- contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol | 2 -- contracts/crowdsale/validation/TimedCrowdsale.sol | 2 +- 10 files changed, 7 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f63d7684f..02033d0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * `ERC20`: `transferFrom` and `_burnFrom ` now emit `Approval` events, to represent the token's state comprehensively through events. ([#1524](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1524)) * `ERC721`: added `_burn(uint256 tokenId)`, replacing the similar deprecated function (see below). ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550)) * `ERC721`: added `_tokensOfOwner(address owner)`, allowing to internally retrieve the array of an account's owned tokens. ([#1522](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1522)) + * Crowdsales: all constructors are now `public`, meaning it is not necessary to extend these contracts in order to deploy them. The exception is `FinalizableCrowdsale`, since it is meaningless unless extended. ([#1564](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1564)) * `SafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559)) ### Improvements: diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index 451f902de..f03a0a383 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -53,7 +53,7 @@ contract Crowdsale is ReentrancyGuard { * @param wallet Address where collected funds will be forwarded to * @param token Address of the token being sold */ - constructor (uint256 rate, address wallet, IERC20 token) internal { + constructor (uint256 rate, address wallet, IERC20 token) public { require(rate > 0); require(wallet != address(0)); require(token != address(0)); diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index 9d4de3b09..1e5ff7494 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -12,8 +12,6 @@ contract PostDeliveryCrowdsale is TimedCrowdsale { mapping(address => uint256) private _balances; - constructor () internal {} - /** * @dev Withdraw tokens only after crowdsale ends. * @param beneficiary Whose tokens will be withdrawn. diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index 4ef5dffd4..ad12a6075 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -27,7 +27,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale { * @dev Constructor, creates RefundEscrow. * @param goal Funding goal */ - constructor (uint256 goal) internal { + constructor (uint256 goal) public { require(goal > 0); _escrow = new RefundEscrow(wallet()); _goal = goal; diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index b0c09c744..adb4036ed 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -20,7 +20,7 @@ contract AllowanceCrowdsale is Crowdsale { * @dev Constructor, takes token wallet address. * @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale */ - constructor (address tokenWallet) internal { + constructor (address tokenWallet) public { require(tokenWallet != address(0)); _tokenWallet = tokenWallet; } diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index 1f346a819..ba42131e5 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -9,8 +9,6 @@ import "../../token/ERC20/ERC20Mintable.sol"; * Token ownership should be transferred to MintedCrowdsale for minting. */ contract MintedCrowdsale is Crowdsale { - constructor () internal {} - /** * @dev Overrides delivery by minting tokens upon purchase. * @param beneficiary Token purchaser diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 5ac7731a5..72da45c47 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -20,7 +20,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { * @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale * @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale */ - constructor (uint256 initialRate, uint256 finalRate) internal { + constructor (uint256 initialRate, uint256 finalRate) public { require(finalRate > 0); require(initialRate > finalRate); _initialRate = initialRate; diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 2b49362c2..1429ea162 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -16,7 +16,7 @@ contract CappedCrowdsale is Crowdsale { * @dev Constructor, takes maximum amount of wei accepted in the crowdsale. * @param cap Max amount of wei to be contributed */ - constructor (uint256 cap) internal { + constructor (uint256 cap) public { require(cap > 0); _cap = cap; } diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index 1bae0f96b..289ca1f3a 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -14,8 +14,6 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole { mapping(address => uint256) private _contributions; mapping(address => uint256) private _caps; - constructor () internal {} - /** * @dev Sets a specific beneficiary's maximum contribution. * @param beneficiary Address to be capped diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index 244220034..cf6806398 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -26,7 +26,7 @@ contract TimedCrowdsale is Crowdsale { * @param openingTime Crowdsale opening time * @param closingTime Crowdsale closing time */ - constructor (uint256 openingTime, uint256 closingTime) internal { + constructor (uint256 openingTime, uint256 closingTime) public { // solium-disable-next-line security/no-block-members require(openingTime >= block.timestamp); require(closingTime > openingTime); From 02f9727dd88705363d766f7c472fe7c81facce6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Tue, 18 Dec 2018 16:34:28 -0300 Subject: [PATCH 191/205] Release candidate v2.1.0-rc.1 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index a60b4a603..c53270424 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.0.0", + "version": "2.1.0-rc.1", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index b5ce5da27..16511c717 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0", + "version": "2.1.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f4b6b0fbc..fc57658c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.0.0", + "version": "2.1.0-rc.1", "description": "Secure Smart Contract library for Solidity", "files": [ "build", From be5ed7364b93daccbb74a09e3f5ec1be6c458097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 20 Dec 2018 12:26:43 -0300 Subject: [PATCH 192/205] Release v2.1.0 solc 0.5.x (#1568) * Now compiling in a separate directory using truffle 5. * Ported to 0.5.1, now compiling using 0.5.1. * test now also compiles using the truffle 5 hack. * Downgraded to 0.5.0. * Sorted scripts. * Cleaned up the compile script a bit. --- .gitignore | 3 ++ contracts/access/Roles.sol | 2 +- contracts/access/roles/CapperRole.sol | 2 +- contracts/access/roles/MinterRole.sol | 2 +- contracts/access/roles/PauserRole.sol | 2 +- contracts/access/roles/SignerRole.sol | 2 +- contracts/access/roles/WhitelistedRole.sol | 2 +- contracts/access/roles/WhitelisterRole.sol | 2 +- contracts/crowdsale/Crowdsale.sol | 10 ++--- .../distribution/FinalizableCrowdsale.sol | 2 +- .../distribution/PostDeliveryCrowdsale.sol | 2 +- .../distribution/RefundableCrowdsale.sol | 4 +- .../RefundablePostDeliveryCrowdsale.sol | 2 +- .../crowdsale/emission/AllowanceCrowdsale.sol | 4 +- .../crowdsale/emission/MintedCrowdsale.sol | 2 +- .../price/IncreasingPriceCrowdsale.sol | 2 +- .../crowdsale/validation/CappedCrowdsale.sol | 2 +- .../IndividuallyCappedCrowdsale.sol | 2 +- .../validation/PausableCrowdsale.sol | 2 +- .../crowdsale/validation/TimedCrowdsale.sol | 2 +- .../validation/WhitelistCrowdsale.sol | 2 +- contracts/cryptography/ECDSA.sol | 4 +- contracts/cryptography/MerkleProof.sol | 4 +- contracts/drafts/Counter.sol | 2 +- contracts/drafts/ERC1046/TokenMetadata.sol | 8 ++-- contracts/drafts/ERC20Migrator.sol | 14 +++---- contracts/drafts/SignatureBouncer.sol | 16 +++---- contracts/drafts/TokenVesting.sol | 18 ++++---- contracts/examples/SampleCrowdsale.sol | 4 +- contracts/examples/SimpleToken.sol | 7 ++-- contracts/introspection/ERC165.sol | 2 +- contracts/introspection/ERC165Checker.sol | 4 +- contracts/introspection/IERC165.sol | 2 +- contracts/lifecycle/Pausable.sol | 2 +- contracts/math/Math.sol | 2 +- contracts/math/SafeMath.sol | 2 +- contracts/mocks/Acknowledger.sol | 2 +- contracts/mocks/AddressImpl.sol | 2 +- contracts/mocks/AllowanceCrowdsaleImpl.sol | 4 +- contracts/mocks/ArraysImpl.sol | 4 +- contracts/mocks/CappedCrowdsaleImpl.sol | 4 +- contracts/mocks/CapperRoleMock.sol | 2 +- contracts/mocks/ConditionalEscrowMock.sol | 2 +- contracts/mocks/CounterImpl.sol | 4 +- contracts/mocks/CrowdsaleMock.sol | 4 +- contracts/mocks/DetailedERC20Mock.sol | 4 +- contracts/mocks/ECDSAMock.sol | 4 +- .../ERC165/ERC165InterfacesSupported.sol | 4 +- contracts/mocks/ERC165/ERC165NotSupported.sol | 2 +- contracts/mocks/ERC165CheckerMock.sol | 4 +- contracts/mocks/ERC165Mock.sol | 2 +- contracts/mocks/ERC20BurnableMock.sol | 2 +- contracts/mocks/ERC20MintableMock.sol | 2 +- contracts/mocks/ERC20Mock.sol | 2 +- contracts/mocks/ERC20PausableMock.sol | 2 +- contracts/mocks/ERC20WithMetadataMock.sol | 4 +- contracts/mocks/ERC721FullMock.sol | 6 +-- .../mocks/ERC721MintableBurnableImpl.sol | 2 +- contracts/mocks/ERC721Mock.sol | 2 +- contracts/mocks/ERC721PausableMock.sol | 2 +- contracts/mocks/ERC721ReceiverMock.sol | 4 +- contracts/mocks/EventEmitter.sol | 12 +++--- contracts/mocks/Failer.sol | 2 +- contracts/mocks/FinalizableCrowdsaleImpl.sol | 4 +- .../mocks/IncreasingPriceCrowdsaleImpl.sol | 4 +- .../mocks/IndividuallyCappedCrowdsaleImpl.sol | 4 +- contracts/mocks/MathMock.sol | 2 +- contracts/mocks/MerkleProofWrapper.sol | 4 +- contracts/mocks/MintedCrowdsaleImpl.sol | 4 +- contracts/mocks/MinterRoleMock.sol | 2 +- contracts/mocks/OwnableInterfaceId.sol | 2 +- contracts/mocks/OwnableMock.sol | 2 +- contracts/mocks/PausableCrowdsaleImpl.sol | 4 +- contracts/mocks/PausableMock.sol | 2 +- contracts/mocks/PauserRoleMock.sol | 2 +- contracts/mocks/PostDeliveryCrowdsaleImpl.sol | 4 +- contracts/mocks/PullPaymentMock.sol | 2 +- contracts/mocks/ReentrancyAttack.sol | 5 ++- contracts/mocks/ReentrancyMock.sol | 6 +-- contracts/mocks/RefundableCrowdsaleImpl.sol | 4 +- .../RefundablePostDeliveryCrowdsaleImpl.sol | 4 +- contracts/mocks/RolesMock.sol | 2 +- contracts/mocks/SafeERC20Helper.sol | 8 ++-- contracts/mocks/SafeMathMock.sol | 2 +- contracts/mocks/SecondaryMock.sol | 2 +- contracts/mocks/SignatureBouncerMock.sol | 16 +++---- contracts/mocks/SignerRoleMock.sol | 2 +- contracts/mocks/TimedCrowdsaleImpl.sol | 4 +- contracts/mocks/WhitelistCrowdsaleImpl.sol | 4 +- contracts/mocks/WhitelistedRoleMock.sol | 2 +- contracts/mocks/WhitelisterRoleMock.sol | 2 +- contracts/ownership/Ownable.sol | 2 +- contracts/ownership/Secondary.sol | 2 +- contracts/payment/PaymentSplitter.sol | 6 +-- contracts/payment/PullPayment.sol | 4 +- .../payment/escrow/ConditionalEscrow.sol | 4 +- contracts/payment/escrow/Escrow.sol | 4 +- contracts/payment/escrow/RefundEscrow.sol | 6 +-- contracts/token/ERC20/ERC20.sol | 2 +- contracts/token/ERC20/ERC20Burnable.sol | 2 +- contracts/token/ERC20/ERC20Capped.sol | 2 +- contracts/token/ERC20/ERC20Detailed.sol | 8 ++-- contracts/token/ERC20/ERC20Mintable.sol | 2 +- contracts/token/ERC20/ERC20Pausable.sol | 2 +- contracts/token/ERC20/IERC20.sol | 2 +- contracts/token/ERC20/SafeERC20.sol | 2 +- contracts/token/ERC20/TokenTimelock.sol | 2 +- contracts/token/ERC721/ERC721.sol | 8 ++-- contracts/token/ERC721/ERC721Burnable.sol | 2 +- contracts/token/ERC721/ERC721Enumerable.sol | 2 +- contracts/token/ERC721/ERC721Full.sol | 4 +- contracts/token/ERC721/ERC721Holder.sol | 4 +- contracts/token/ERC721/ERC721Metadata.sol | 12 +++--- .../token/ERC721/ERC721MetadataMintable.sol | 4 +- contracts/token/ERC721/ERC721Mintable.sol | 2 +- contracts/token/ERC721/ERC721Pausable.sol | 2 +- contracts/token/ERC721/IERC721.sol | 4 +- contracts/token/ERC721/IERC721Enumerable.sol | 2 +- contracts/token/ERC721/IERC721Full.sol | 2 +- contracts/token/ERC721/IERC721Metadata.sol | 8 ++-- contracts/token/ERC721/IERC721Receiver.sol | 4 +- contracts/utils/Address.sol | 2 +- contracts/utils/Arrays.sol | 2 +- contracts/utils/ReentrancyGuard.sol | 2 +- package.json | 17 ++++---- scripts/build.sh | 2 +- scripts/compile.sh | 42 +++++++++++++++++++ 127 files changed, 284 insertions(+), 236 deletions(-) create mode 100755 scripts/compile.sh diff --git a/.gitignore b/.gitignore index 7c53c0042..2c8d17d4f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ build/ # truffle .node-xmlhttprequest-* + +# Temporary directory for 0.5.x compilation +solc-0.5 diff --git a/contracts/access/Roles.sol b/contracts/access/Roles.sol index 7b364da53..63148d1f1 100644 --- a/contracts/access/Roles.sol +++ b/contracts/access/Roles.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Roles diff --git a/contracts/access/roles/CapperRole.sol b/contracts/access/roles/CapperRole.sol index 7307abce1..94bc6e2f0 100644 --- a/contracts/access/roles/CapperRole.sol +++ b/contracts/access/roles/CapperRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; diff --git a/contracts/access/roles/MinterRole.sol b/contracts/access/roles/MinterRole.sol index c4234c5bc..61e70f64f 100644 --- a/contracts/access/roles/MinterRole.sol +++ b/contracts/access/roles/MinterRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; diff --git a/contracts/access/roles/PauserRole.sol b/contracts/access/roles/PauserRole.sol index 5963feffd..2882d0ecc 100644 --- a/contracts/access/roles/PauserRole.sol +++ b/contracts/access/roles/PauserRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; diff --git a/contracts/access/roles/SignerRole.sol b/contracts/access/roles/SignerRole.sol index 0dc182705..8021cfd2b 100644 --- a/contracts/access/roles/SignerRole.sol +++ b/contracts/access/roles/SignerRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; diff --git a/contracts/access/roles/WhitelistedRole.sol b/contracts/access/roles/WhitelistedRole.sol index 68a826197..040d4db58 100644 --- a/contracts/access/roles/WhitelistedRole.sol +++ b/contracts/access/roles/WhitelistedRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; import "./WhitelisterRole.sol"; diff --git a/contracts/access/roles/WhitelisterRole.sol b/contracts/access/roles/WhitelisterRole.sol index 0abdeaaf7..8812db6ed 100644 --- a/contracts/access/roles/WhitelisterRole.sol +++ b/contracts/access/roles/WhitelisterRole.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Roles.sol"; diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index f03a0a383..3e188b447 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../math/SafeMath.sol"; @@ -25,7 +25,7 @@ contract Crowdsale is ReentrancyGuard { IERC20 private _token; // Address where funds are collected - address private _wallet; + address payable private _wallet; // How many token units a buyer gets per wei. // The rate is the conversion between wei and the smallest and indivisible token unit. @@ -53,10 +53,10 @@ contract Crowdsale is ReentrancyGuard { * @param wallet Address where collected funds will be forwarded to * @param token Address of the token being sold */ - constructor (uint256 rate, address wallet, IERC20 token) public { + constructor (uint256 rate, address payable wallet, IERC20 token) public { require(rate > 0); require(wallet != address(0)); - require(token != address(0)); + require(address(token) != address(0)); _rate = rate; _wallet = wallet; @@ -87,7 +87,7 @@ contract Crowdsale is ReentrancyGuard { /** * @return the address where funds are collected. */ - function wallet() public view returns (address) { + function wallet() public view returns (address payable) { return _wallet; } diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index 22ae5ba05..7573a3e9a 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "../validation/TimedCrowdsale.sol"; diff --git a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol index 1e5ff7494..6e10fa540 100644 --- a/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../validation/TimedCrowdsale.sol"; import "../../math/SafeMath.sol"; diff --git a/contracts/crowdsale/distribution/RefundableCrowdsale.sol b/contracts/crowdsale/distribution/RefundableCrowdsale.sol index ad12a6075..732103a1f 100644 --- a/contracts/crowdsale/distribution/RefundableCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundableCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "./FinalizableCrowdsale.sol"; @@ -44,7 +44,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale { * @dev Investors can claim refunds here if crowdsale is unsuccessful * @param refundee Whose refund will be claimed. */ - function claimRefund(address refundee) public { + function claimRefund(address payable refundee) public { require(finalized()); require(!goalReached()); diff --git a/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol b/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol index 1586a19d1..be4c5b6a0 100644 --- a/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol +++ b/contracts/crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./RefundableCrowdsale.sol"; import "./PostDeliveryCrowdsale.sol"; diff --git a/contracts/crowdsale/emission/AllowanceCrowdsale.sol b/contracts/crowdsale/emission/AllowanceCrowdsale.sol index adb4036ed..b4f3aceb4 100644 --- a/contracts/crowdsale/emission/AllowanceCrowdsale.sol +++ b/contracts/crowdsale/emission/AllowanceCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Crowdsale.sol"; import "../../token/ERC20/IERC20.sol"; @@ -37,7 +37,7 @@ contract AllowanceCrowdsale is Crowdsale { * @return Amount of tokens left in the allowance */ function remainingTokens() public view returns (uint256) { - return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, this)); + return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, address(this))); } /** diff --git a/contracts/crowdsale/emission/MintedCrowdsale.sol b/contracts/crowdsale/emission/MintedCrowdsale.sol index ba42131e5..f239735e0 100644 --- a/contracts/crowdsale/emission/MintedCrowdsale.sol +++ b/contracts/crowdsale/emission/MintedCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Crowdsale.sol"; import "../../token/ERC20/ERC20Mintable.sol"; diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 72da45c47..51e946c7d 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../validation/TimedCrowdsale.sol"; import "../../math/SafeMath.sol"; diff --git a/contracts/crowdsale/validation/CappedCrowdsale.sol b/contracts/crowdsale/validation/CappedCrowdsale.sol index 1429ea162..2d21c0418 100644 --- a/contracts/crowdsale/validation/CappedCrowdsale.sol +++ b/contracts/crowdsale/validation/CappedCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; diff --git a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol index 289ca1f3a..34bc09519 100644 --- a/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol +++ b/contracts/crowdsale/validation/IndividuallyCappedCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; diff --git a/contracts/crowdsale/validation/PausableCrowdsale.sol b/contracts/crowdsale/validation/PausableCrowdsale.sol index 65fb0019f..cbaf08a16 100644 --- a/contracts/crowdsale/validation/PausableCrowdsale.sol +++ b/contracts/crowdsale/validation/PausableCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.5.0; import "../Crowdsale.sol"; import "../../lifecycle/Pausable.sol"; diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index cf6806398..418df3bcb 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "../Crowdsale.sol"; diff --git a/contracts/crowdsale/validation/WhitelistCrowdsale.sol b/contracts/crowdsale/validation/WhitelistCrowdsale.sol index d93028d59..16e28786e 100644 --- a/contracts/crowdsale/validation/WhitelistCrowdsale.sol +++ b/contracts/crowdsale/validation/WhitelistCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../Crowdsale.sol"; import "../../access/roles/WhitelistedRole.sol"; diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index 4c91663ec..be7bc3d55 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Elliptic curve signature operations @@ -13,7 +13,7 @@ library ECDSA { * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. * @param signature bytes signature, the signature is generated using web3.eth.sign() */ - function recover(bytes32 hash, bytes signature) internal pure returns (address) { + function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; diff --git a/contracts/cryptography/MerkleProof.sol b/contracts/cryptography/MerkleProof.sol index 31e469367..2a964c8ba 100644 --- a/contracts/cryptography/MerkleProof.sol +++ b/contracts/cryptography/MerkleProof.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title MerkleProof @@ -13,7 +13,7 @@ library MerkleProof { * @param root Merkle root * @param leaf Leaf of Merkle tree */ - function verify(bytes32[] proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { + function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { diff --git a/contracts/drafts/Counter.sol b/contracts/drafts/Counter.sol index 12bcf0848..af8f1e45d 100644 --- a/contracts/drafts/Counter.sol +++ b/contracts/drafts/Counter.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Counter diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index 460887221..1569d1b00 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../token/ERC20/IERC20.sol"; @@ -9,17 +9,17 @@ import "../../token/ERC20/IERC20.sol"; * @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/IERC721.sol#L17 when 1046 is finalized */ contract ERC20TokenMetadata is IERC20 { - function tokenURI() external view returns (string); + function tokenURI() external view returns (string memory); } contract ERC20WithMetadata is ERC20TokenMetadata { string private _tokenURI; - constructor (string tokenURI) public { + constructor (string memory tokenURI) public { _tokenURI = tokenURI; } - function tokenURI() external view returns (string) { + function tokenURI() external view returns (string memory) { return _tokenURI; } } diff --git a/contracts/drafts/ERC20Migrator.sol b/contracts/drafts/ERC20Migrator.sol index 83a0401ff..ae07399a6 100644 --- a/contracts/drafts/ERC20Migrator.sol +++ b/contracts/drafts/ERC20Migrator.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/ERC20Mintable.sol"; @@ -44,7 +44,7 @@ contract ERC20Migrator { * @param legacyToken address of the old token contract */ constructor (IERC20 legacyToken) public { - require(legacyToken != address(0)); + require(address(legacyToken) != address(0)); _legacyToken = legacyToken; } @@ -68,9 +68,9 @@ contract ERC20Migrator { * @param newToken the token that will be minted */ function beginMigration(ERC20Mintable newToken) public { - require(_newToken == address(0)); - require(newToken != address(0)); - require(newToken.isMinter(this)); + require(address(_newToken) == address(0)); + require(address(newToken) != address(0)); + require(newToken.isMinter(address(this))); _newToken = newToken; } @@ -82,7 +82,7 @@ contract ERC20Migrator { * @param amount amount of tokens to be migrated */ function migrate(address account, uint256 amount) public { - _legacyToken.safeTransferFrom(account, this, amount); + _legacyToken.safeTransferFrom(account, address(this), amount); _newToken.mint(account, amount); } @@ -93,7 +93,7 @@ contract ERC20Migrator { */ function migrateAll(address account) public { uint256 balance = _legacyToken.balanceOf(account); - uint256 allowance = _legacyToken.allowance(account, this); + uint256 allowance = _legacyToken.allowance(account, address(this)); uint256 amount = Math.min(balance, allowance); migrate(account, amount); } diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index e0e33fcff..f0d6f29ca 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/SignerRole.sol"; import "../cryptography/ECDSA.sol"; @@ -48,7 +48,7 @@ contract SignatureBouncer is SignerRole { /** * @dev requires that a valid signature of a signer was provided */ - modifier onlyValidSignature(bytes signature) { + modifier onlyValidSignature(bytes memory signature) { require(_isValidSignature(msg.sender, signature)); _; } @@ -56,7 +56,7 @@ contract SignatureBouncer is SignerRole { /** * @dev requires that a valid signature with a specifed method of a signer was provided */ - modifier onlyValidSignatureAndMethod(bytes signature) { + modifier onlyValidSignatureAndMethod(bytes memory signature) { require(_isValidSignatureAndMethod(msg.sender, signature)); _; } @@ -64,7 +64,7 @@ contract SignatureBouncer is SignerRole { /** * @dev requires that a valid signature with a specifed method and params of a signer was provided */ - modifier onlyValidSignatureAndData(bytes signature) { + modifier onlyValidSignatureAndData(bytes memory signature) { require(_isValidSignatureAndData(msg.sender, signature)); _; } @@ -73,7 +73,7 @@ contract SignatureBouncer is SignerRole { * @dev is the signature of `this + sender` from a signer? * @return bool */ - function _isValidSignature(address account, bytes signature) internal view returns (bool) { + function _isValidSignature(address account, bytes memory signature) internal view returns (bool) { return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature); } @@ -81,7 +81,7 @@ contract SignatureBouncer is SignerRole { * @dev is the signature of `this + sender + methodId` from a signer? * @return bool */ - function _isValidSignatureAndMethod(address account, bytes signature) internal view returns (bool) { + function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) { bytes memory data = new bytes(_METHOD_ID_SIZE); for (uint i = 0; i < data.length; i++) { data[i] = msg.data[i]; @@ -94,7 +94,7 @@ contract SignatureBouncer is SignerRole { * @notice the signature parameter of the method being validated must be the "last" parameter * @return bool */ - function _isValidSignatureAndData(address account, bytes signature) internal view returns (bool) { + function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) { require(msg.data.length > _SIGNATURE_SIZE); bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); @@ -110,7 +110,7 @@ contract SignatureBouncer is SignerRole { * and then recover the signature and check it against the signer role * @return bool */ - function _isValidDataHash(bytes32 hash, bytes signature) internal view returns (bool) { + function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) { address signer = hash.toEthSignedMessageHash().recover(signature); return signer != address(0) && isSigner(signer); diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index d8ea749e1..6c6f34a11 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -1,6 +1,6 @@ /* solium-disable security/no-block-members */ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/SafeERC20.sol"; import "../ownership/Ownable.sol"; @@ -112,11 +112,11 @@ contract TokenVesting is Ownable { require(unreleased > 0); - _released[token] = _released[token].add(unreleased); + _released[address(token)] = _released[address(token)].add(unreleased); token.safeTransfer(_beneficiary, unreleased); - emit TokensReleased(token, unreleased); + emit TokensReleased(address(token), unreleased); } /** @@ -126,18 +126,18 @@ contract TokenVesting is Ownable { */ function revoke(IERC20 token) public onlyOwner { require(_revocable); - require(!_revoked[token]); + require(!_revoked[address(token)]); uint256 balance = token.balanceOf(address(this)); uint256 unreleased = _releasableAmount(token); uint256 refund = balance.sub(unreleased); - _revoked[token] = true; + _revoked[address(token)] = true; token.safeTransfer(owner(), refund); - emit TokenVestingRevoked(token); + emit TokenVestingRevoked(address(token)); } /** @@ -145,7 +145,7 @@ contract TokenVesting is Ownable { * @param token ERC20 token which is being vested */ function _releasableAmount(IERC20 token) private view returns (uint256) { - return _vestedAmount(token).sub(_released[token]); + return _vestedAmount(token).sub(_released[address(token)]); } /** @@ -154,11 +154,11 @@ contract TokenVesting is Ownable { */ function _vestedAmount(IERC20 token) private view returns (uint256) { uint256 currentBalance = token.balanceOf(address(this)); - uint256 totalBalance = currentBalance.add(_released[token]); + uint256 totalBalance = currentBalance.add(_released[address(token)]); if (block.timestamp < _cliff) { return 0; - } else if (block.timestamp >= _start.add(_duration) || _revoked[token]) { + } else if (block.timestamp >= _start.add(_duration) || _revoked[address(token)]) { return totalBalance; } else { return totalBalance.mul(block.timestamp.sub(_start)).div(_duration); diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 45bf24b11..b120e88c6 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../crowdsale/validation/CappedCrowdsale.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; @@ -38,7 +38,7 @@ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsal uint256 openingTime, uint256 closingTime, uint256 rate, - address wallet, + address payable wallet, uint256 cap, ERC20Mintable token, uint256 goal diff --git a/contracts/examples/SimpleToken.sol b/contracts/examples/SimpleToken.sol index 95b31ea37..50a4f433f 100644 --- a/contracts/examples/SimpleToken.sol +++ b/contracts/examples/SimpleToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; @@ -10,12 +10,13 @@ import "../token/ERC20/ERC20Detailed.sol"; * `ERC20` functions. */ contract SimpleToken is ERC20, ERC20Detailed { - uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals())); + uint8 public constant DECIMALS = 18; + uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(DECIMALS)); /** * @dev Constructor that gives msg.sender all of existing tokens. */ - constructor () public ERC20Detailed("SimpleToken", "SIM", 18) { + constructor () public ERC20Detailed("SimpleToken", "SIM", DECIMALS) { _mint(msg.sender, INITIAL_SUPPLY); } } diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index f1dfbcff1..8903be17f 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC165.sol"; diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index e40db319e..6a0fb9ff6 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title ERC165Checker @@ -49,7 +49,7 @@ library ERC165Checker { * interfaceIds list, false otherwise * @dev Interface identification is specified in ERC-165. */ - function _supportsAllInterfaces(address account, bytes4[] interfaceIds) internal view returns (bool) { + function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!_supportsERC165(account)) { return false; diff --git a/contracts/introspection/IERC165.sol b/contracts/introspection/IERC165.sol index da133b0b4..393e6fb29 100644 --- a/contracts/introspection/IERC165.sol +++ b/contracts/introspection/IERC165.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title IERC165 diff --git a/contracts/lifecycle/Pausable.sol b/contracts/lifecycle/Pausable.sol index d74759440..9c7298971 100644 --- a/contracts/lifecycle/Pausable.sol +++ b/contracts/lifecycle/Pausable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/PauserRole.sol"; diff --git a/contracts/math/Math.sol b/contracts/math/Math.sol index b57f0d3e6..1cdc075f0 100644 --- a/contracts/math/Math.sol +++ b/contracts/math/Math.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Math diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index 777f62016..9d65897a0 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title SafeMath diff --git a/contracts/mocks/Acknowledger.sol b/contracts/mocks/Acknowledger.sol index ff8f1ae04..f3f514cb0 100644 --- a/contracts/mocks/Acknowledger.sol +++ b/contracts/mocks/Acknowledger.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract Acknowledger { event AcknowledgeFoo(uint256 a); diff --git a/contracts/mocks/AddressImpl.sol b/contracts/mocks/AddressImpl.sol index b60fe618f..a73591c37 100644 --- a/contracts/mocks/AddressImpl.sol +++ b/contracts/mocks/AddressImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../utils/Address.sol"; diff --git a/contracts/mocks/AllowanceCrowdsaleImpl.sol b/contracts/mocks/AllowanceCrowdsaleImpl.sol index 67e94fd48..944ec21a6 100644 --- a/contracts/mocks/AllowanceCrowdsaleImpl.sol +++ b/contracts/mocks/AllowanceCrowdsaleImpl.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/emission/AllowanceCrowdsale.sol"; contract AllowanceCrowdsaleImpl is AllowanceCrowdsale { - constructor (uint256 rate, address wallet, IERC20 token, address tokenWallet) + constructor (uint256 rate, address payable wallet, IERC20 token, address tokenWallet) public Crowdsale(rate, wallet, token) AllowanceCrowdsale(tokenWallet) diff --git a/contracts/mocks/ArraysImpl.sol b/contracts/mocks/ArraysImpl.sol index 77c7a517b..b2067526d 100644 --- a/contracts/mocks/ArraysImpl.sol +++ b/contracts/mocks/ArraysImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../utils/Arrays.sol"; @@ -7,7 +7,7 @@ contract ArraysImpl { uint256[] private array; - constructor (uint256[] _array) public { + constructor (uint256[] memory _array) public { array = _array; } diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index 4b8cd5560..4c5811b65 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/CappedCrowdsale.sol"; contract CappedCrowdsaleImpl is CappedCrowdsale { - constructor (uint256 rate, address wallet, IERC20 token, uint256 cap) + constructor (uint256 rate, address payable wallet, IERC20 token, uint256 cap) public Crowdsale(rate, wallet, token) CappedCrowdsale(cap) diff --git a/contracts/mocks/CapperRoleMock.sol b/contracts/mocks/CapperRoleMock.sol index eb3b92b62..090502068 100644 --- a/contracts/mocks/CapperRoleMock.sol +++ b/contracts/mocks/CapperRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/CapperRole.sol"; diff --git a/contracts/mocks/ConditionalEscrowMock.sol b/contracts/mocks/ConditionalEscrowMock.sol index 2f1faf804..4b39ba386 100644 --- a/contracts/mocks/ConditionalEscrowMock.sol +++ b/contracts/mocks/ConditionalEscrowMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../payment/escrow/ConditionalEscrow.sol"; diff --git a/contracts/mocks/CounterImpl.sol b/contracts/mocks/CounterImpl.sol index 15ff1361e..4d976f55d 100644 --- a/contracts/mocks/CounterImpl.sol +++ b/contracts/mocks/CounterImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../drafts/Counter.sol"; @@ -10,7 +10,7 @@ contract CounterImpl { // use whatever key you want to track your counters mapping(string => Counter.Counter) private _counters; - function doThing(string key) public returns (uint256) { + function doThing(string memory key) public returns (uint256) { theId = _counters[key].next(); return theId; } diff --git a/contracts/mocks/CrowdsaleMock.sol b/contracts/mocks/CrowdsaleMock.sol index 0555b1abc..007f49ee8 100644 --- a/contracts/mocks/CrowdsaleMock.sol +++ b/contracts/mocks/CrowdsaleMock.sol @@ -1,7 +1,7 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../crowdsale/Crowdsale.sol"; contract CrowdsaleMock is Crowdsale { - constructor (uint256 rate, address wallet, IERC20 token) public Crowdsale(rate, wallet, token) {} + constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {} } diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index fbc526c45..bd45c34b5 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -1,8 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; contract ERC20DetailedMock is ERC20, ERC20Detailed { - constructor (string name, string symbol, uint8 decimals) ERC20Detailed(name, symbol, decimals) public {} + constructor (string memory name, string memory symbol, uint8 decimals) ERC20Detailed(name, symbol, decimals) public {} } diff --git a/contracts/mocks/ECDSAMock.sol b/contracts/mocks/ECDSAMock.sol index 862ad9b35..977f324ac 100644 --- a/contracts/mocks/ECDSAMock.sol +++ b/contracts/mocks/ECDSAMock.sol @@ -1,11 +1,11 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../cryptography/ECDSA.sol"; contract ECDSAMock { using ECDSA for bytes32; - function recover(bytes32 hash, bytes signature) public pure returns (address) { + function recover(bytes32 hash, bytes memory signature) public pure returns (address) { return hash.recover(signature); } diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 0ed65df24..9eb7060ed 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../introspection/IERC165.sol"; @@ -47,7 +47,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { } contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock { - constructor (bytes4[] interfaceIds) public { + constructor (bytes4[] memory interfaceIds) public { for (uint256 i = 0; i < interfaceIds.length; i++) { _registerInterface(interfaceIds[i]); } diff --git a/contracts/mocks/ERC165/ERC165NotSupported.sol b/contracts/mocks/ERC165/ERC165NotSupported.sol index c1a39db19..d77baedf3 100644 --- a/contracts/mocks/ERC165/ERC165NotSupported.sol +++ b/contracts/mocks/ERC165/ERC165NotSupported.sol @@ -1,3 +1,3 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract ERC165NotSupported {} diff --git a/contracts/mocks/ERC165CheckerMock.sol b/contracts/mocks/ERC165CheckerMock.sol index b85397b44..db1853de0 100644 --- a/contracts/mocks/ERC165CheckerMock.sol +++ b/contracts/mocks/ERC165CheckerMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../introspection/ERC165Checker.sol"; @@ -13,7 +13,7 @@ contract ERC165CheckerMock { return account._supportsInterface(interfaceId); } - function supportsAllInterfaces(address account, bytes4[] interfaceIds) public view returns (bool) { + function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) { return account._supportsAllInterfaces(interfaceIds); } } diff --git a/contracts/mocks/ERC165Mock.sol b/contracts/mocks/ERC165Mock.sol index ad48a9de3..e21581b52 100644 --- a/contracts/mocks/ERC165Mock.sol +++ b/contracts/mocks/ERC165Mock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../introspection/ERC165.sol"; diff --git a/contracts/mocks/ERC20BurnableMock.sol b/contracts/mocks/ERC20BurnableMock.sol index 7456f9642..20db0b9a4 100644 --- a/contracts/mocks/ERC20BurnableMock.sol +++ b/contracts/mocks/ERC20BurnableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20Burnable.sol"; diff --git a/contracts/mocks/ERC20MintableMock.sol b/contracts/mocks/ERC20MintableMock.sol index 31384c790..3e74e8f92 100644 --- a/contracts/mocks/ERC20MintableMock.sol +++ b/contracts/mocks/ERC20MintableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20Mintable.sol"; import "./MinterRoleMock.sol"; diff --git a/contracts/mocks/ERC20Mock.sol b/contracts/mocks/ERC20Mock.sol index 3742f808d..857cf3ff1 100644 --- a/contracts/mocks/ERC20Mock.sol +++ b/contracts/mocks/ERC20Mock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20.sol"; diff --git a/contracts/mocks/ERC20PausableMock.sol b/contracts/mocks/ERC20PausableMock.sol index 59a8a0952..4c9cdb7f8 100644 --- a/contracts/mocks/ERC20PausableMock.sol +++ b/contracts/mocks/ERC20PausableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20Pausable.sol"; import "./PauserRoleMock.sol"; diff --git a/contracts/mocks/ERC20WithMetadataMock.sol b/contracts/mocks/ERC20WithMetadataMock.sol index 6eb4b9306..ea61bd3f3 100644 --- a/contracts/mocks/ERC20WithMetadataMock.sol +++ b/contracts/mocks/ERC20WithMetadataMock.sol @@ -1,8 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20.sol"; import "../drafts/ERC1046/TokenMetadata.sol"; contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { - constructor (string tokenURI) public ERC20WithMetadata(tokenURI) {} + constructor (string memory tokenURI) public ERC20WithMetadata(tokenURI) {} } diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index d917e8f63..a21c59d36 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; @@ -11,7 +11,7 @@ import "../token/ERC721/ERC721Burnable.sol"; * checking token existence, removal of a token from an address */ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { - constructor (string name, string symbol) public ERC721Mintable() ERC721Full(name, symbol) {} + constructor (string memory name, string memory symbol) public ERC721Mintable() ERC721Full(name, symbol) {} function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); @@ -21,7 +21,7 @@ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, E return _tokensOfOwner(owner); } - function setTokenURI(uint256 tokenId, string uri) public { + function setTokenURI(uint256 tokenId, string memory uri) public { _setTokenURI(tokenId, uri); } } diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index 6e5aae6f5..169dc7790 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC721/ERC721Full.sol"; import "../token/ERC721/ERC721Mintable.sol"; diff --git a/contracts/mocks/ERC721Mock.sol b/contracts/mocks/ERC721Mock.sol index f953d944d..b02df5d21 100644 --- a/contracts/mocks/ERC721Mock.sol +++ b/contracts/mocks/ERC721Mock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC721/ERC721.sol"; diff --git a/contracts/mocks/ERC721PausableMock.sol b/contracts/mocks/ERC721PausableMock.sol index bd6ea8df8..f46f9e776 100644 --- a/contracts/mocks/ERC721PausableMock.sol +++ b/contracts/mocks/ERC721PausableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC721/ERC721Pausable.sol"; import "./PauserRoleMock.sol"; diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 7e469b271..0bf650c21 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC721/IERC721Receiver.sol"; @@ -13,7 +13,7 @@ contract ERC721ReceiverMock is IERC721Receiver { _reverts = reverts; } - function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public returns (bytes4) { + function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4) { require(!_reverts); emit Received(operator, from, tokenId, data, gasleft()); return _retval; diff --git a/contracts/mocks/EventEmitter.sol b/contracts/mocks/EventEmitter.sol index 0a954f37b..4ffc77c4b 100644 --- a/contracts/mocks/EventEmitter.sol +++ b/contracts/mocks/EventEmitter.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract EventEmitter { event Argumentless(); @@ -11,7 +11,7 @@ contract EventEmitter { event String(string value); event LongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue); - constructor (uint8 uintValue, bool booleanValue, string stringValue) public { + constructor (uint8 uintValue, bool booleanValue, string memory stringValue) public { emit ShortUint(uintValue); emit Boolean(booleanValue); emit String(stringValue); @@ -45,11 +45,11 @@ contract EventEmitter { emit Boolean(value); } - function emitString(string value) public { + function emitString(string memory value) public { emit String(value); } - function emitLongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue) public { + function emitLongUintBooleanString(uint256 uintValue, bool booleanValue, string memory stringValue) public { emit LongUintBooleanString(uintValue, booleanValue, stringValue); } @@ -58,7 +58,7 @@ contract EventEmitter { emit Boolean(boolValue); } - function emitStringAndEmitIndirectly(string value, IndirectEventEmitter emitter) public { + function emitStringAndEmitIndirectly(string memory value, IndirectEventEmitter emitter) public { emit String(value); emitter.emitStringIndirectly(value); } @@ -67,7 +67,7 @@ contract EventEmitter { contract IndirectEventEmitter { event IndirectString(string value); - function emitStringIndirectly(string value) public { + function emitStringIndirectly(string memory value) public { emit IndirectString(value); } } diff --git a/contracts/mocks/Failer.sol b/contracts/mocks/Failer.sol index 2b25be41e..77bdae0f7 100644 --- a/contracts/mocks/Failer.sol +++ b/contracts/mocks/Failer.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract Failer { uint256[] private array; diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 0dee94ff1..6622d15a5 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -1,11 +1,11 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/FinalizableCrowdsale.sol"; contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { - constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) diff --git a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol index 3f5d30b21..bcb37e9cd 100644 --- a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol +++ b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../crowdsale/price/IncreasingPriceCrowdsale.sol"; import "../math/SafeMath.sol"; @@ -7,7 +7,7 @@ contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale { constructor ( uint256 openingTime, uint256 closingTime, - address wallet, + address payable wallet, IERC20 token, uint256 initialRate, uint256 finalRate diff --git a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol index 296dbc26f..83e8f6e53 100644 --- a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol +++ b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol"; import "./CapperRoleMock.sol"; contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock { - constructor (uint256 rate, address wallet, IERC20 token) public Crowdsale(rate, wallet, token) + constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {} } diff --git a/contracts/mocks/MathMock.sol b/contracts/mocks/MathMock.sol index c6d1f107a..2461fe902 100644 --- a/contracts/mocks/MathMock.sol +++ b/contracts/mocks/MathMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../math/Math.sol"; diff --git a/contracts/mocks/MerkleProofWrapper.sol b/contracts/mocks/MerkleProofWrapper.sol index 02a1d8cc6..23c72b269 100644 --- a/contracts/mocks/MerkleProofWrapper.sol +++ b/contracts/mocks/MerkleProofWrapper.sol @@ -1,9 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import { MerkleProof } from "../cryptography/MerkleProof.sol"; contract MerkleProofWrapper { - function verify(bytes32[] proof, bytes32 root, bytes32 leaf) public pure returns (bool) { + function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) public pure returns (bool) { return MerkleProof.verify(proof, root, leaf); } } diff --git a/contracts/mocks/MintedCrowdsaleImpl.sol b/contracts/mocks/MintedCrowdsaleImpl.sol index 48d6c167d..16f2a1c02 100644 --- a/contracts/mocks/MintedCrowdsaleImpl.sol +++ b/contracts/mocks/MintedCrowdsaleImpl.sol @@ -1,8 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; contract MintedCrowdsaleImpl is MintedCrowdsale { - constructor (uint256 rate, address wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) {} + constructor (uint256 rate, address payable wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) {} } diff --git a/contracts/mocks/MinterRoleMock.sol b/contracts/mocks/MinterRoleMock.sol index 0755c1221..7e1d7d15d 100644 --- a/contracts/mocks/MinterRoleMock.sol +++ b/contracts/mocks/MinterRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/MinterRole.sol"; diff --git a/contracts/mocks/OwnableInterfaceId.sol b/contracts/mocks/OwnableInterfaceId.sol index 14c943d50..363d9a2ac 100644 --- a/contracts/mocks/OwnableInterfaceId.sol +++ b/contracts/mocks/OwnableInterfaceId.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ownership/Ownable.sol"; diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol index 6a1bf1e2c..f64f8e7a0 100644 --- a/contracts/mocks/OwnableMock.sol +++ b/contracts/mocks/OwnableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ownership/Ownable.sol"; diff --git a/contracts/mocks/PausableCrowdsaleImpl.sol b/contracts/mocks/PausableCrowdsaleImpl.sol index 64b4bc578..8ac695078 100644 --- a/contracts/mocks/PausableCrowdsaleImpl.sol +++ b/contracts/mocks/PausableCrowdsaleImpl.sol @@ -1,9 +1,9 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.5.0; import "../token/ERC20/ERC20.sol"; import "../crowdsale/validation/PausableCrowdsale.sol"; contract PausableCrowdsaleImpl is PausableCrowdsale { - constructor (uint256 _rate, address _wallet, ERC20 _token) public Crowdsale(_rate, _wallet, _token) { + constructor (uint256 _rate, address payable _wallet, ERC20 _token) public Crowdsale(_rate, _wallet, _token) { } } diff --git a/contracts/mocks/PausableMock.sol b/contracts/mocks/PausableMock.sol index c2dcda1c5..8e9ae03d3 100644 --- a/contracts/mocks/PausableMock.sol +++ b/contracts/mocks/PausableMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../lifecycle/Pausable.sol"; import "./PauserRoleMock.sol"; diff --git a/contracts/mocks/PauserRoleMock.sol b/contracts/mocks/PauserRoleMock.sol index 22f03f5b0..b6dce92b4 100644 --- a/contracts/mocks/PauserRoleMock.sol +++ b/contracts/mocks/PauserRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/PauserRole.sol"; diff --git a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol index df71456c7..b612ac518 100644 --- a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/PostDeliveryCrowdsale.sol"; contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale { - constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token) public TimedCrowdsale(openingTime, closingTime) Crowdsale(rate, wallet, token) diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index d35e97e02..1ecddccd3 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../payment/PullPayment.sol"; diff --git a/contracts/mocks/ReentrancyAttack.sol b/contracts/mocks/ReentrancyAttack.sol index c18a1020b..a4675f986 100644 --- a/contracts/mocks/ReentrancyAttack.sol +++ b/contracts/mocks/ReentrancyAttack.sol @@ -1,10 +1,11 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract ReentrancyAttack { function callSender(bytes4 data) public { // solium-disable-next-line security/no-low-level-calls - require(msg.sender.call(abi.encodeWithSelector(data))); + (bool success,) = msg.sender.call(abi.encodeWithSelector(data)); + require(success); } } diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index 5aac7603c..b314e54f0 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../utils/ReentrancyGuard.sol"; import "./ReentrancyAttack.sol"; @@ -25,8 +25,8 @@ contract ReentrancyMock is ReentrancyGuard { if (n > 0) { count(); // solium-disable-next-line security/no-low-level-calls - bool result = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); - require(result == true); + (bool success,) = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); + require(success); } } diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index 325653b5f..9e466867b 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/RefundableCrowdsale.sol"; @@ -8,7 +8,7 @@ contract RefundableCrowdsaleImpl is RefundableCrowdsale { uint256 openingTime, uint256 closingTime, uint256 rate, - address wallet, + address payable wallet, IERC20 token, uint256 goal ) diff --git a/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol index 06f21d71b..6772971c8 100644 --- a/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol"; @@ -8,7 +8,7 @@ contract RefundablePostDeliveryCrowdsaleImpl is RefundablePostDeliveryCrowdsale uint256 openingTime, uint256 closingTime, uint256 rate, - address wallet, + address payable wallet, IERC20 token, uint256 goal ) diff --git a/contracts/mocks/RolesMock.sol b/contracts/mocks/RolesMock.sol index db71ca536..4b0f0de0a 100644 --- a/contracts/mocks/RolesMock.sol +++ b/contracts/mocks/RolesMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/Roles.sol"; diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index 9c0af1312..e374ead8c 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/SafeERC20.sol"; @@ -54,8 +54,8 @@ contract SafeERC20Helper { IERC20 private _succeeding; constructor () public { - _failing = IERC20(new ERC20FailingMock()); - _succeeding = IERC20(new ERC20SucceedingMock()); + _failing = IERC20(address(new ERC20FailingMock())); + _succeeding = IERC20(address(new ERC20SucceedingMock())); } // Using _failing @@ -103,7 +103,7 @@ contract SafeERC20Helper { } function setAllowance(uint256 allowance_) public { - ERC20SucceedingMock(_succeeding).setAllowance(allowance_); + ERC20SucceedingMock(address(_succeeding)).setAllowance(allowance_); } function allowance() public view returns (uint256) { diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index dba3e88c8..b61683d3e 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../math/SafeMath.sol"; diff --git a/contracts/mocks/SecondaryMock.sol b/contracts/mocks/SecondaryMock.sol index faf88f4e3..b20b5c2a0 100644 --- a/contracts/mocks/SecondaryMock.sol +++ b/contracts/mocks/SecondaryMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ownership/Secondary.sol"; diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index 21572102a..b31fb1986 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -1,28 +1,28 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../drafts/SignatureBouncer.sol"; import "./SignerRoleMock.sol"; contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { - function checkValidSignature(address account, bytes signature) public view returns (bool) { + function checkValidSignature(address account, bytes memory signature) public view returns (bool) { return _isValidSignature(account, signature); } - function onlyWithValidSignature(bytes signature) public onlyValidSignature(signature) view {} + function onlyWithValidSignature(bytes memory signature) public onlyValidSignature(signature) view {} - function checkValidSignatureAndMethod(address account, bytes signature) public view returns (bool) { + function checkValidSignatureAndMethod(address account, bytes memory signature) public view returns (bool) { return _isValidSignatureAndMethod(account, signature); } - function onlyWithValidSignatureAndMethod(bytes signature) public onlyValidSignatureAndMethod(signature) view {} + function onlyWithValidSignatureAndMethod(bytes memory signature) public onlyValidSignatureAndMethod(signature) view {} - function checkValidSignatureAndData(address account, bytes, uint, bytes signature) public view returns (bool) { + function checkValidSignatureAndData(address account, bytes memory, uint, bytes memory signature) public view returns (bool) { return _isValidSignatureAndData(account, signature); } - function onlyWithValidSignatureAndData(uint, bytes signature) public onlyValidSignatureAndData(signature) view {} + function onlyWithValidSignatureAndData(uint, bytes memory signature) public onlyValidSignatureAndData(signature) view {} - function theWrongMethod(bytes) public pure {} + function theWrongMethod(bytes memory) public pure {} function tooShortMsgData() public onlyValidSignatureAndData("") view {} } diff --git a/contracts/mocks/SignerRoleMock.sol b/contracts/mocks/SignerRoleMock.sol index 7eb3c3475..f9ed2876a 100644 --- a/contracts/mocks/SignerRoleMock.sol +++ b/contracts/mocks/SignerRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/SignerRole.sol"; diff --git a/contracts/mocks/TimedCrowdsaleImpl.sol b/contracts/mocks/TimedCrowdsaleImpl.sol index b826c31e5..63bf24cce 100644 --- a/contracts/mocks/TimedCrowdsaleImpl.sol +++ b/contracts/mocks/TimedCrowdsaleImpl.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/TimedCrowdsale.sol"; contract TimedCrowdsaleImpl is TimedCrowdsale { - constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address wallet, IERC20 token) + constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) diff --git a/contracts/mocks/WhitelistCrowdsaleImpl.sol b/contracts/mocks/WhitelistCrowdsaleImpl.sol index ab8bd73fa..6682e392e 100644 --- a/contracts/mocks/WhitelistCrowdsaleImpl.sol +++ b/contracts/mocks/WhitelistCrowdsaleImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../token/ERC20/IERC20.sol"; import "../crowdsale/validation/WhitelistCrowdsale.sol"; @@ -6,5 +6,5 @@ import "../crowdsale/Crowdsale.sol"; contract WhitelistCrowdsaleImpl is Crowdsale, WhitelistCrowdsale { - constructor (uint256 _rate, address _wallet, IERC20 _token) Crowdsale(_rate, _wallet, _token) public {} + constructor (uint256 _rate, address payable _wallet, IERC20 _token) Crowdsale(_rate, _wallet, _token) public {} } diff --git a/contracts/mocks/WhitelistedRoleMock.sol b/contracts/mocks/WhitelistedRoleMock.sol index b710c38d4..34761a548 100644 --- a/contracts/mocks/WhitelistedRoleMock.sol +++ b/contracts/mocks/WhitelistedRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/WhitelistedRole.sol"; diff --git a/contracts/mocks/WhitelisterRoleMock.sol b/contracts/mocks/WhitelisterRoleMock.sol index 06ea7dd63..714410410 100644 --- a/contracts/mocks/WhitelisterRoleMock.sol +++ b/contracts/mocks/WhitelisterRoleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../access/roles/WhitelisterRole.sol"; diff --git a/contracts/ownership/Ownable.sol b/contracts/ownership/Ownable.sol index 5ab46c511..4d3558f16 100644 --- a/contracts/ownership/Ownable.sol +++ b/contracts/ownership/Ownable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Ownable diff --git a/contracts/ownership/Secondary.sol b/contracts/ownership/Secondary.sol index e12cf3cb4..3ca57e4a7 100644 --- a/contracts/ownership/Secondary.sol +++ b/contracts/ownership/Secondary.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Secondary diff --git a/contracts/payment/PaymentSplitter.sol b/contracts/payment/PaymentSplitter.sol index 0b07e62ba..280e4b9ac 100644 --- a/contracts/payment/PaymentSplitter.sol +++ b/contracts/payment/PaymentSplitter.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../math/SafeMath.sol"; @@ -24,7 +24,7 @@ contract PaymentSplitter { /** * @dev Constructor */ - constructor (address[] payees, uint256[] shares) public payable { + constructor (address[] memory payees, uint256[] memory shares) public payable { require(payees.length == shares.length); require(payees.length > 0); @@ -79,7 +79,7 @@ contract PaymentSplitter { * @dev Release one of the payee's proportional payment. * @param account Whose payments will be released. */ - function release(address account) public { + function release(address payable account) public { require(_shares[account] > 0); uint256 totalReceived = address(this).balance.add(_totalReleased); diff --git a/contracts/payment/PullPayment.sol b/contracts/payment/PullPayment.sol index 9517638be..ad961e47b 100644 --- a/contracts/payment/PullPayment.sol +++ b/contracts/payment/PullPayment.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./escrow/Escrow.sol"; @@ -18,7 +18,7 @@ contract PullPayment { * @dev Withdraw accumulated balance. * @param payee Whose balance will be withdrawn. */ - function withdrawPayments(address payee) public { + function withdrawPayments(address payable payee) public { _escrow.withdraw(payee); } diff --git a/contracts/payment/escrow/ConditionalEscrow.sol b/contracts/payment/escrow/ConditionalEscrow.sol index 8697b4f93..268d731fa 100644 --- a/contracts/payment/escrow/ConditionalEscrow.sol +++ b/contracts/payment/escrow/ConditionalEscrow.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./Escrow.sol"; @@ -15,7 +15,7 @@ contract ConditionalEscrow is Escrow { */ function withdrawalAllowed(address payee) public view returns (bool); - function withdraw(address payee) public { + function withdraw(address payable payee) public { require(withdrawalAllowed(payee)); super.withdraw(payee); } diff --git a/contracts/payment/escrow/Escrow.sol b/contracts/payment/escrow/Escrow.sol index 088df38ff..c010add45 100644 --- a/contracts/payment/escrow/Escrow.sol +++ b/contracts/payment/escrow/Escrow.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../math/SafeMath.sol"; import "../../ownership/Secondary.sol"; @@ -42,7 +42,7 @@ contract Escrow is Secondary { * @dev Withdraw accumulated balance for a payee. * @param payee The address whose funds will be withdrawn and transferred to. */ - function withdraw(address payee) public onlyPrimary { + function withdraw(address payable payee) public onlyPrimary { uint256 payment = _deposits[payee]; _deposits[payee] = 0; diff --git a/contracts/payment/escrow/RefundEscrow.sol b/contracts/payment/escrow/RefundEscrow.sol index 67f00e580..18c6fd355 100644 --- a/contracts/payment/escrow/RefundEscrow.sol +++ b/contracts/payment/escrow/RefundEscrow.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ConditionalEscrow.sol"; @@ -20,13 +20,13 @@ contract RefundEscrow is ConditionalEscrow { event RefundsEnabled(); State private _state; - address private _beneficiary; + address payable private _beneficiary; /** * @dev Constructor. * @param beneficiary The beneficiary of the deposits. */ - constructor (address beneficiary) public { + constructor (address payable beneficiary) public { require(beneficiary != address(0)); _beneficiary = beneficiary; _state = State.Active; diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index b41f64462..318445fc4 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; diff --git a/contracts/token/ERC20/ERC20Burnable.sol b/contracts/token/ERC20/ERC20Burnable.sol index 9f1120016..324275711 100644 --- a/contracts/token/ERC20/ERC20Burnable.sol +++ b/contracts/token/ERC20/ERC20Burnable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC20.sol"; diff --git a/contracts/token/ERC20/ERC20Capped.sol b/contracts/token/ERC20/ERC20Capped.sol index 2d6c35326..3d4a2f1ab 100644 --- a/contracts/token/ERC20/ERC20Capped.sol +++ b/contracts/token/ERC20/ERC20Capped.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC20Mintable.sol"; diff --git a/contracts/token/ERC20/ERC20Detailed.sol b/contracts/token/ERC20/ERC20Detailed.sol index 02f1648da..71c0b0159 100644 --- a/contracts/token/ERC20/ERC20Detailed.sol +++ b/contracts/token/ERC20/ERC20Detailed.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC20.sol"; @@ -13,7 +13,7 @@ contract ERC20Detailed is IERC20 { string private _symbol; uint8 private _decimals; - constructor (string name, string symbol, uint8 decimals) public { + constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; @@ -22,14 +22,14 @@ contract ERC20Detailed is IERC20 { /** * @return the name of the token. */ - function name() public view returns (string) { + function name() public view returns (string memory) { return _name; } /** * @return the symbol of the token. */ - function symbol() public view returns (string) { + function symbol() public view returns (string memory) { return _symbol; } diff --git a/contracts/token/ERC20/ERC20Mintable.sol b/contracts/token/ERC20/ERC20Mintable.sol index ec30caa48..c6c0d647b 100644 --- a/contracts/token/ERC20/ERC20Mintable.sol +++ b/contracts/token/ERC20/ERC20Mintable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC20.sol"; import "../../access/roles/MinterRole.sol"; diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index b3947d589..e54228eaa 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC20.sol"; import "../../lifecycle/Pausable.sol"; diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index 7c44280f0..5ae0a6d93 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title ERC20 interface diff --git a/contracts/token/ERC20/SafeERC20.sol b/contracts/token/ERC20/SafeERC20.sol index adb217e0b..25ac9bae7 100644 --- a/contracts/token/ERC20/SafeERC20.sol +++ b/contracts/token/ERC20/SafeERC20.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index a69680507..f8899d212 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./SafeERC20.sol"; diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 007f6e580..6d177e8d9 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; @@ -163,7 +163,7 @@ contract ERC721 is ERC165, IERC721 { * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ - function safeTransferFrom(address from, address to, uint256 tokenId, bytes _data) public { + function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { transferFrom(from, to, tokenId); // solium-disable-next-line arg-overflow require(_checkOnERC721Received(from, to, tokenId, _data)); @@ -227,7 +227,7 @@ contract ERC721 is ERC165, IERC721 { emit Transfer(owner, address(0), tokenId); } - + /** * @dev Internal function to burn a specific token * Reverts if the token does not exist @@ -267,7 +267,7 @@ contract ERC721 is ERC165, IERC721 { * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ - function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes _data) internal returns (bool) { + function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { if (!to.isContract()) { return true; } diff --git a/contracts/token/ERC721/ERC721Burnable.sol b/contracts/token/ERC721/ERC721Burnable.sol index d8cb5e13f..21bdc51a3 100644 --- a/contracts/token/ERC721/ERC721Burnable.sol +++ b/contracts/token/ERC721/ERC721Burnable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721.sol"; diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index a543c75f7..e1f291ea3 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721Enumerable.sol"; import "./ERC721.sol"; diff --git a/contracts/token/ERC721/ERC721Full.sol b/contracts/token/ERC721/ERC721Full.sol index 1c964ea8e..2db57305c 100644 --- a/contracts/token/ERC721/ERC721Full.sol +++ b/contracts/token/ERC721/ERC721Full.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721.sol"; import "./ERC721Enumerable.sol"; @@ -11,5 +11,5 @@ import "./ERC721Metadata.sol"; * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata { - constructor (string name, string symbol) ERC721Metadata(name, symbol) public {} + constructor (string memory name, string memory symbol) ERC721Metadata(name, symbol) public {} } diff --git a/contracts/token/ERC721/ERC721Holder.sol b/contracts/token/ERC721/ERC721Holder.sol index 87480b9fa..bcc10d7e2 100644 --- a/contracts/token/ERC721/ERC721Holder.sol +++ b/contracts/token/ERC721/ERC721Holder.sol @@ -1,9 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721Receiver.sol"; contract ERC721Holder is IERC721Receiver { - function onERC721Received(address, address, uint256, bytes) public returns (bytes4) { + function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) { return this.onERC721Received.selector; } } diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index df0379294..703d524b2 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721.sol"; import "./IERC721Metadata.sol"; @@ -25,7 +25,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { /** * @dev Constructor function */ - constructor (string name, string symbol) public { + constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; @@ -37,7 +37,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * @dev Gets the token name * @return string representing the token name */ - function name() external view returns (string) { + function name() external view returns (string memory) { return _name; } @@ -45,7 +45,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * @dev Gets the token symbol * @return string representing the token symbol */ - function symbol() external view returns (string) { + function symbol() external view returns (string memory) { return _symbol; } @@ -54,7 +54,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ - function tokenURI(uint256 tokenId) external view returns (string) { + function tokenURI(uint256 tokenId) external view returns (string memory) { require(_exists(tokenId)); return _tokenURIs[tokenId]; } @@ -65,7 +65,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { * @param tokenId uint256 ID of the token to set its URI * @param uri string URI to assign */ - function _setTokenURI(uint256 tokenId, string uri) internal { + function _setTokenURI(uint256 tokenId, string memory uri) internal { require(_exists(tokenId)); _tokenURIs[tokenId] = uri; } diff --git a/contracts/token/ERC721/ERC721MetadataMintable.sol b/contracts/token/ERC721/ERC721MetadataMintable.sol index 6e20f83a3..01a1a5174 100644 --- a/contracts/token/ERC721/ERC721MetadataMintable.sol +++ b/contracts/token/ERC721/ERC721MetadataMintable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721Metadata.sol"; import "../../access/roles/MinterRole.sol"; @@ -16,7 +16,7 @@ contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { * @param tokenURI The token URI of the minted token. * @return A boolean that indicates if the operation was successful. */ - function mintWithTokenURI(address to, uint256 tokenId, string tokenURI) public onlyMinter returns (bool) { + function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public onlyMinter returns (bool) { _mint(to, tokenId); _setTokenURI(tokenId, tokenURI); return true; diff --git a/contracts/token/ERC721/ERC721Mintable.sol b/contracts/token/ERC721/ERC721Mintable.sol index 48a7f2095..7e7503d0a 100644 --- a/contracts/token/ERC721/ERC721Mintable.sol +++ b/contracts/token/ERC721/ERC721Mintable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721.sol"; import "../../access/roles/MinterRole.sol"; diff --git a/contracts/token/ERC721/ERC721Pausable.sol b/contracts/token/ERC721/ERC721Pausable.sol index 0fb2ef3b5..656df2387 100644 --- a/contracts/token/ERC721/ERC721Pausable.sol +++ b/contracts/token/ERC721/ERC721Pausable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ERC721.sol"; import "../../lifecycle/Pausable.sol"; diff --git a/contracts/token/ERC721/IERC721.sol b/contracts/token/ERC721/IERC721.sol index 003802182..4aa303896 100644 --- a/contracts/token/ERC721/IERC721.sol +++ b/contracts/token/ERC721/IERC721.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../introspection/IERC165.sol"; @@ -23,5 +23,5 @@ contract IERC721 is IERC165 { function transferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom(address from, address to, uint256 tokenId) public; - function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) public; + function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public; } diff --git a/contracts/token/ERC721/IERC721Enumerable.sol b/contracts/token/ERC721/IERC721Enumerable.sol index 06a50ed1b..80df93f4f 100644 --- a/contracts/token/ERC721/IERC721Enumerable.sol +++ b/contracts/token/ERC721/IERC721Enumerable.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721.sol"; diff --git a/contracts/token/ERC721/IERC721Full.sol b/contracts/token/ERC721/IERC721Full.sol index 90d8c21d8..9779a8204 100644 --- a/contracts/token/ERC721/IERC721Full.sol +++ b/contracts/token/ERC721/IERC721Full.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721.sol"; import "./IERC721Enumerable.sol"; diff --git a/contracts/token/ERC721/IERC721Metadata.sol b/contracts/token/ERC721/IERC721Metadata.sol index 2d7d1b249..ee87a158c 100644 --- a/contracts/token/ERC721/IERC721Metadata.sol +++ b/contracts/token/ERC721/IERC721Metadata.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IERC721.sol"; @@ -7,7 +7,7 @@ import "./IERC721.sol"; * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Metadata is IERC721 { - function name() external view returns (string); - function symbol() external view returns (string); - function tokenURI(uint256 tokenId) external view returns (string); + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function tokenURI(uint256 tokenId) external view returns (string memory); } diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol index 7c360d7b4..0d13d66a1 100644 --- a/contracts/token/ERC721/IERC721Receiver.sol +++ b/contracts/token/ERC721/IERC721Receiver.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title ERC721 token receiver interface @@ -20,5 +20,5 @@ contract IERC721Receiver { * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ - function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public returns (bytes4); + function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4); } diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index c44dfa17f..8b6d4255e 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * Utility library of inline functions on addresses diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol index 67f6a784e..c34154c52 100644 --- a/contracts/utils/Arrays.sol +++ b/contracts/utils/Arrays.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../math/Math.sol"; diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 40af0f688..86ab57cf8 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Helps contracts guard against reentrancy attacks. diff --git a/package.json b/package.json index fc57658c7..dc4fd8aaf 100644 --- a/package.json +++ b/package.json @@ -8,18 +8,19 @@ "test" ], "scripts": { - "test": "scripts/test.sh", + "build": "scripts/build.sh", + "compile": "scripts/compile.sh", + "console": "truffle console", + "coverage": "scripts/coverage.sh", + "lint": "npm run lint:js && npm run lint:sol", + "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", "lint:js": "eslint .", "lint:js:fix": "eslint . --fix", "lint:sol": "solium -d .", "lint:sol:fix": "solium -d . --fix", - "lint": "npm run lint:js && npm run lint:sol", - "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", - "console": "truffle console", - "coverage": "scripts/coverage.sh", - "version": "scripts/version.js", - "build": "scripts/build.sh", - "prepack": "npm run build" + "prepack": "npm run build", + "test": "npm run compile && scripts/test.sh", + "version": "scripts/version.js" }, "repository": { "type": "git", diff --git a/scripts/build.sh b/scripts/build.sh index f48b92d06..ff2f37c44 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -16,7 +16,7 @@ do done < contracts/.npmignore # Compile everything else. -node_modules/.bin/truffle compile +npm run compile # Return ignored files to their place. mv "$tmp_dir/"* contracts/ diff --git a/scripts/compile.sh b/scripts/compile.sh new file mode 100755 index 000000000..7de7b6ca0 --- /dev/null +++ b/scripts/compile.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Configure to exit script as soon as a command fails. +set -o errexit + +SOLC_05_DIR=solc-0.5 + +# Delete any previous build artifacts +rm -rf build/ + +# Create a subproject where 0.5.x compilation will take place +mkdir -p "$SOLC_05_DIR" + +cd "$SOLC_05_DIR" +npm init --yes +npm install --save-dev truffle@5.0.0 + +rm -rf contracts +ln --symbolic ../contracts contracts + +# Delete any previous build artifacts +rm -rf build/ + +# Compile +echo " +module.exports = { + compilers: { + solc: { + version: \"0.5.0\", + }, + }, +}; +" > truffle-config.js + +npx truffle compile + +# Modify the paths in the artifacts to make it look as if they were built in the root +sed --in-place --expression "s/\/$SOLC_05_DIR//g" build/contracts/*.json + +# Copy them back into the root +cd .. +cp --recursive "$SOLC_05_DIR"/build build From 4b8fcbcee16437d8a29bc0e5bb328b2a1547f996 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Sat, 22 Dec 2018 17:10:44 -0300 Subject: [PATCH 193/205] remove linux-specific mktemp usage (#1571) (cherry picked from commit 7361ffd26b6354499d0b68d6d2d9da1f8cb21c8b) --- scripts/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build.sh b/scripts/build.sh index ff2f37c44..ec4607756 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -7,7 +7,8 @@ set -o errexit rm -rf build # Create a temporary directory to place ignored files (e.g. examples). -tmp_dir="$(mktemp -dp.)" +tmp_dir="ignored_contracts" +mkdir "$tmp_dir" # Move the ignored files to the temporary directory. while IFS="" read -r ignored From daa301fef01bf94875579a4785c0e0b2a5896ea7 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 18 Dec 2018 17:11:25 -0300 Subject: [PATCH 194/205] remove note about 2.0 being experimental (#1565) (cherry picked from commit 503674167d9081be056dd9d0c262dbcbb537128c) --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index b6f9ed67d..8f12460a2 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,6 @@ npm install openzeppelin-solidity ``` -If you're interested in trying out a preview of OpenZeppelin 2.0, install `openzeppelin-solidity@next`, check out the [release notes](https://github.com/OpenZeppelin/openzeppelin-solidity/releases/tag/v2.0.0-rc.1), and let us know what you think! - ## Usage To write your custom contracts, import ours and extend them through inheritance. From 13eff701123038cde1e5282864325b21e70366e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 19 Dec 2018 14:19:18 -0300 Subject: [PATCH 195/205] Updated PausableCrowdsale to require solc ^0.4.24 (#1567) (cherry picked from commit 73cbad2f78b3d0e4f0a715d0afa2a0b12f7084e1) --- contracts/crowdsale/validation/PausableCrowdsale.sol | 2 +- contracts/mocks/PausableCrowdsaleImpl.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/crowdsale/validation/PausableCrowdsale.sol b/contracts/crowdsale/validation/PausableCrowdsale.sol index 65fb0019f..71a4d1442 100644 --- a/contracts/crowdsale/validation/PausableCrowdsale.sol +++ b/contracts/crowdsale/validation/PausableCrowdsale.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.4.24; import "../Crowdsale.sol"; import "../../lifecycle/Pausable.sol"; diff --git a/contracts/mocks/PausableCrowdsaleImpl.sol b/contracts/mocks/PausableCrowdsaleImpl.sol index 64b4bc578..1eddc11b9 100644 --- a/contracts/mocks/PausableCrowdsaleImpl.sol +++ b/contracts/mocks/PausableCrowdsaleImpl.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.4.24; import "../token/ERC20/ERC20.sol"; import "../crowdsale/validation/PausableCrowdsale.sol"; From 8c20d53789481fad8b05f7127dcf3a490fbc6e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 27 Dec 2018 16:24:38 -0300 Subject: [PATCH 196/205] Updated changelog to reflect 0.5 support. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02033d0b7..e47d98e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.1.0 (unreleased) ### New features: + * Now targeting the 0.5.x line of Solidity compilers. For 0.4.24 support, use version 2.0 of OpenZeppelin. * `WhitelistCrowdsale`: a crowdsale where only whitelisted accounts (`WhitelistedRole`) can purchase tokens. Adding or removing accounts from the whitelist is done by whitelisters (`WhitelisterRole`). Similar to the pre-2.0 `WhitelistedCrowdsale`. ([#1525](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1525)) * `RefundablePostDeliveryCrowdsale`: replacement for `RefundableCrowdsale` (deprecated, see below) where tokens are only granted once the crowdsale ends (if it meets its goal). ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543)) * `PausableCrowdsale`: allows for pausers (`PauserRole`) to pause token purchases. Other crowdsale operations (e.g. withdrawals and refunds, if applicable) are not affected. ([#832](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/832)) From 40f08a8c0b162dd296180366ef78273702e0ac43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 27 Dec 2018 16:25:02 -0300 Subject: [PATCH 197/205] Release candidate v2.1.0-rc.2 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index c53270424..5c3c06fb3 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.1.0-rc.1", + "version": "2.1.0-rc.2", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index 16511c717..7d0594d02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0-rc.1", + "version": "2.1.0-rc.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index dc4fd8aaf..9dcecbc2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0-rc.1", + "version": "2.1.0-rc.2", "description": "Secure Smart Contract library for Solidity", "files": [ "build", From a5b14f262e6f2148a5ba0319866443085929ad4c Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 4 Jan 2019 14:57:04 -0300 Subject: [PATCH 198/205] Separate unsigned and signed safemath libraries (#1588) * separate unsigned and signed safemath libraries * update changelog entry for SignedSafeMath --- CHANGELOG.md | 2 +- contracts/drafts/SignedSafeMath.sol | 60 +++++ contracts/math/SafeMath.sol | 55 +---- contracts/mocks/SafeMathMock.sol | 28 +-- contracts/mocks/SignedSafeMathMock.sol | 21 ++ test/drafts/SignedSafeMath.test.js | 138 +++++++++++ test/math/SafeMath.test.js | 330 ++++++++----------------- 7 files changed, 326 insertions(+), 308 deletions(-) create mode 100644 contracts/drafts/SignedSafeMath.sol create mode 100644 contracts/mocks/SignedSafeMathMock.sol create mode 100644 test/drafts/SignedSafeMath.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index e47d98e0b..03974ab30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ * `ERC721`: added `_burn(uint256 tokenId)`, replacing the similar deprecated function (see below). ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550)) * `ERC721`: added `_tokensOfOwner(address owner)`, allowing to internally retrieve the array of an account's owned tokens. ([#1522](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1522)) * Crowdsales: all constructors are now `public`, meaning it is not necessary to extend these contracts in order to deploy them. The exception is `FinalizableCrowdsale`, since it is meaningless unless extended. ([#1564](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1564)) - * `SafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559)) + * `SignedSafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559), [#1588](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1588)) ### Improvements: * The compiler version required by `Array` was behind the rest of the libray so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553)) diff --git a/contracts/drafts/SignedSafeMath.sol b/contracts/drafts/SignedSafeMath.sol new file mode 100644 index 000000000..4e6ab0af7 --- /dev/null +++ b/contracts/drafts/SignedSafeMath.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.5.0; + +/** + * @title SignedSafeMath + * @dev Signed math operations with safety checks that revert on error + */ +library SignedSafeMath { + int256 constant private INT256_MIN = -2**255; + + /** + * @dev Multiplies two signed integers, reverts on overflow. + */ + function mul(int256 a, int256 b) internal pure returns (int256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below + + int256 c = a * b; + require(c / a == b); + + return c; + } + + /** + * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. + */ + function div(int256 a, int256 b) internal pure returns (int256) { + require(b != 0); // Solidity only automatically asserts when dividing by 0 + require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow + + int256 c = a / b; + + return c; + } + + /** + * @dev Subtracts two signed integers, reverts on overflow. + */ + function sub(int256 a, int256 b) internal pure returns (int256) { + int256 c = a - b; + require((b >= 0 && c <= a) || (b < 0 && c > a)); + + return c; + } + + /** + * @dev Adds two signed integers, reverts on overflow. + */ + function add(int256 a, int256 b) internal pure returns (int256) { + int256 c = a + b; + require((b >= 0 && c >= a) || (b < 0 && c < a)); + + return c; + } +} diff --git a/contracts/math/SafeMath.sol b/contracts/math/SafeMath.sol index 9d65897a0..54ab43acf 100644 --- a/contracts/math/SafeMath.sol +++ b/contracts/math/SafeMath.sol @@ -2,11 +2,9 @@ pragma solidity ^0.5.0; /** * @title SafeMath - * @dev Math operations with safety checks that revert on error + * @dev Unsigned math operations with safety checks that revert on error */ library SafeMath { - int256 constant private INT256_MIN = -2**255; - /** * @dev Multiplies two unsigned integers, reverts on overflow. */ @@ -24,25 +22,6 @@ library SafeMath { return c; } - /** - * @dev Multiplies two signed integers, reverts on overflow. - */ - function mul(int256 a, int256 b) internal pure returns (int256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below - - int256 c = a * b; - require(c / a == b); - - return c; - } - /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ @@ -55,18 +34,6 @@ library SafeMath { return c; } - /** - * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. - */ - function div(int256 a, int256 b) internal pure returns (int256) { - require(b != 0); // Solidity only automatically asserts when dividing by 0 - require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow - - int256 c = a / b; - - return c; - } - /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ @@ -77,16 +44,6 @@ library SafeMath { return c; } - /** - * @dev Subtracts two signed integers, reverts on overflow. - */ - function sub(int256 a, int256 b) internal pure returns (int256) { - int256 c = a - b; - require((b >= 0 && c <= a) || (b < 0 && c > a)); - - return c; - } - /** * @dev Adds two unsigned integers, reverts on overflow. */ @@ -97,16 +54,6 @@ library SafeMath { return c; } - /** - * @dev Adds two signed integers, reverts on overflow. - */ - function add(int256 a, int256 b) internal pure returns (int256) { - int256 c = a + b; - require((b >= 0 && c >= a) || (b < 0 && c < a)); - - return c; - } - /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. diff --git a/contracts/mocks/SafeMathMock.sol b/contracts/mocks/SafeMathMock.sol index b61683d3e..43dac5ec2 100644 --- a/contracts/mocks/SafeMathMock.sol +++ b/contracts/mocks/SafeMathMock.sol @@ -1,43 +1,25 @@ pragma solidity ^0.5.0; - import "../math/SafeMath.sol"; - contract SafeMathMock { - function mulUints(uint256 a, uint256 b) public pure returns (uint256) { + function mul(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.mul(a, b); } - function mulInts(int256 a, int256 b) public pure returns (int256) { - return SafeMath.mul(a, b); - } - - function divUints(uint256 a, uint256 b) public pure returns (uint256) { + function div(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.div(a, b); } - function divInts(int256 a, int256 b) public pure returns (int256) { - return SafeMath.div(a, b); - } - - function subUints(uint256 a, uint256 b) public pure returns (uint256) { + function sub(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.sub(a, b); } - function subInts(int256 a, int256 b) public pure returns (int256) { - return SafeMath.sub(a, b); - } - - function addUints(uint256 a, uint256 b) public pure returns (uint256) { + function add(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.add(a, b); } - function addInts(int256 a, int256 b) public pure returns (int256) { - return SafeMath.add(a, b); - } - - function modUints(uint256 a, uint256 b) public pure returns (uint256) { + function mod(uint256 a, uint256 b) public pure returns (uint256) { return SafeMath.mod(a, b); } } diff --git a/contracts/mocks/SignedSafeMathMock.sol b/contracts/mocks/SignedSafeMathMock.sol new file mode 100644 index 000000000..90a3ee642 --- /dev/null +++ b/contracts/mocks/SignedSafeMathMock.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.5.0; + +import "../drafts/SignedSafeMath.sol"; + +contract SignedSafeMathMock { + function mul(int256 a, int256 b) public pure returns (int256) { + return SignedSafeMath.mul(a, b); + } + + function div(int256 a, int256 b) public pure returns (int256) { + return SignedSafeMath.div(a, b); + } + + function sub(int256 a, int256 b) public pure returns (int256) { + return SignedSafeMath.sub(a, b); + } + + function add(int256 a, int256 b) public pure returns (int256) { + return SignedSafeMath.add(a, b); + } +} diff --git a/test/drafts/SignedSafeMath.test.js b/test/drafts/SignedSafeMath.test.js new file mode 100644 index 000000000..e144d39f6 --- /dev/null +++ b/test/drafts/SignedSafeMath.test.js @@ -0,0 +1,138 @@ +const shouldFail = require('../helpers/shouldFail'); +const { MIN_INT256, MAX_INT256 } = require('../helpers/constants'); + +const SignedSafeMathMock = artifacts.require('SignedSafeMathMock'); + +const { BigNumber } = require('../helpers/setup'); + +contract('SignedSafeMath', function () { + beforeEach(async function () { + this.safeMath = await SignedSafeMathMock.new(); + }); + + describe('add', function () { + it('adds correctly if it does not overflow and the result is positve', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + (await this.safeMath.add(a, b)).should.be.bignumber.equal(a.plus(b)); + }); + + it('adds correctly if it does not overflow and the result is negative', async function () { + const a = MAX_INT256; + const b = MIN_INT256; + + const result = await this.safeMath.add(a, b); + result.should.be.bignumber.equal(a.plus(b)); + }); + + it('reverts on positive addition overflow', async function () { + const a = MAX_INT256; + const b = new BigNumber(1); + + await shouldFail.reverting(this.safeMath.add(a, b)); + }); + + it('reverts on negative addition overflow', async function () { + const a = MIN_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.add(a, b)); + }); + }); + + describe('sub', function () { + it('subtracts correctly if it does not overflow and the result is positive', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); + + const result = await this.safeMath.sub(a, b); + result.should.be.bignumber.equal(a.minus(b)); + }); + + it('subtracts correctly if it does not overflow and the result is negative', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); + + const result = await this.safeMath.sub(a, b); + result.should.be.bignumber.equal(a.minus(b)); + }); + + it('reverts on positive subtraction overflow', async function () { + const a = MAX_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.sub(a, b)); + }); + + it('reverts on negative subtraction overflow', async function () { + const a = MIN_INT256; + const b = new BigNumber(1); + + await shouldFail.reverting(this.safeMath.sub(a, b)); + }); + }); + + describe('mul', function () { + it('multiplies correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(-1234); + + const result = await this.safeMath.mul(a, b); + result.should.be.bignumber.equal(a.times(b)); + }); + + it('handles a zero product correctly', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + const result = await this.safeMath.mul(a, b); + result.should.be.bignumber.equal(a.times(b)); + }); + + it('reverts on multiplication overflow, positive operands', async function () { + const a = MAX_INT256; + const b = new BigNumber(2); + + await shouldFail.reverting(this.safeMath.mul(a, b)); + }); + + it('reverts when minimum integer is multiplied by -1', async function () { + const a = MIN_INT256; + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.mul(a, b)); + }); + + it('reverts when -1 is multiplied by minimum integer', async function () { + const a = new BigNumber(-1); + const b = MIN_INT256; + + await shouldFail.reverting(this.safeMath.mul(a, b)); + }); + }); + + describe('div', function () { + it('divides correctly', async function () { + const a = new BigNumber(-5678); + const b = new BigNumber(5678); + + const result = await this.safeMath.div(a, b); + result.should.be.bignumber.equal(a.div(b)); + }); + + it('reverts on zero division', async function () { + const a = new BigNumber(-5678); + const b = new BigNumber(0); + + await shouldFail.reverting(this.safeMath.div(a, b)); + }); + + it('reverts on overflow, negative second', async function () { + const a = new BigNumber(MIN_INT256); + const b = new BigNumber(-1); + + await shouldFail.reverting(this.safeMath.div(a, b)); + }); + }); +}); diff --git a/test/math/SafeMath.test.js b/test/math/SafeMath.test.js index e2cf371ef..221c998ff 100644 --- a/test/math/SafeMath.test.js +++ b/test/math/SafeMath.test.js @@ -1,5 +1,5 @@ const shouldFail = require('../helpers/shouldFail'); -const { MAX_UINT256, MIN_INT256, MAX_INT256 } = require('../helpers/constants'); +const { MAX_UINT256 } = require('../helpers/constants'); const SafeMathMock = artifacts.require('SafeMathMock'); @@ -10,264 +10,134 @@ contract('SafeMath', function () { this.safeMath = await SafeMathMock.new(); }); - describe('unsigned', function () { - describe('add', function () { - it('adds correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(1234); + describe('add', function () { + it('adds correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); - (await this.safeMath.addUints(a, b)).should.be.bignumber.equal(a.plus(b)); - }); - - it('reverts on addition overflow', async function () { - const a = MAX_UINT256; - const b = new BigNumber(1); - - await shouldFail.reverting(this.safeMath.addUints(a, b)); - }); + (await this.safeMath.add(a, b)).should.be.bignumber.equal(a.plus(b)); }); - describe('sub', function () { - it('subtracts correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(1234); + it('reverts on addition overflow', async function () { + const a = MAX_UINT256; + const b = new BigNumber(1); - (await this.safeMath.subUints(a, b)).should.be.bignumber.equal(a.minus(b)); - }); + await shouldFail.reverting(this.safeMath.add(a, b)); + }); + }); - it('reverts if subtraction result would be negative', async function () { - const a = new BigNumber(1234); - const b = new BigNumber(5678); + describe('sub', function () { + it('subtracts correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(1234); - await shouldFail.reverting(this.safeMath.subUints(a, b)); - }); + (await this.safeMath.sub(a, b)).should.be.bignumber.equal(a.minus(b)); }); - describe('mul', function () { - it('multiplies correctly', async function () { - const a = new BigNumber(1234); - const b = new BigNumber(5678); + it('reverts if subtraction result would be negative', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); - (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); - }); + await shouldFail.reverting(this.safeMath.sub(a, b)); + }); + }); - it('handles a zero product correctly (first number as zero)', async function () { - const a = new BigNumber(0); - const b = new BigNumber(5678); + describe('mul', function () { + it('multiplies correctly', async function () { + const a = new BigNumber(1234); + const b = new BigNumber(5678); - (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); - }); - - it('handles a zero product correctly (second number as zero)', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); - - (await this.safeMath.mulUints(a, b)).should.be.bignumber.equal(a.times(b)); - }); - - it('reverts on multiplication overflow', async function () { - const a = MAX_UINT256; - const b = new BigNumber(2); - - await shouldFail.reverting(this.safeMath.mulUints(a, b)); - }); + (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); }); - describe('div', function () { - it('divides correctly', async function () { + it('handles a zero product correctly (first number as zero)', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); + }); + + it('handles a zero product correctly (second number as zero)', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); + + (await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.times(b)); + }); + + it('reverts on multiplication overflow', async function () { + const a = MAX_UINT256; + const b = new BigNumber(2); + + await shouldFail.reverting(this.safeMath.mul(a, b)); + }); + }); + + describe('div', function () { + it('divides correctly', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(5678); + + (await this.safeMath.div(a, b)).should.be.bignumber.equal(a.div(b)); + }); + + it('divides zero correctly', async function () { + const a = new BigNumber(0); + const b = new BigNumber(5678); + + (await this.safeMath.div(a, b)).should.be.bignumber.equal(0); + }); + + it('returns complete number result on non-even division', async function () { + const a = new BigNumber(7000); + const b = new BigNumber(5678); + + (await this.safeMath.div(a, b)).should.be.bignumber.equal(1); + }); + + it('reverts on zero division', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); + + await shouldFail.reverting(this.safeMath.div(a, b)); + }); + }); + + describe('mod', function () { + describe('modulos correctly', async function () { + it('when the dividend is smaller than the divisor', async function () { + const a = new BigNumber(284); + const b = new BigNumber(5678); + + (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); + }); + + it('when the dividend is equal to the divisor', async function () { const a = new BigNumber(5678); const b = new BigNumber(5678); - (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(a.div(b)); + (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); }); - it('divides zero correctly', async function () { - const a = new BigNumber(0); - const b = new BigNumber(5678); - - (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(0); - }); - - it('returns complete number result on non-even division', async function () { + it('when the dividend is larger than the divisor', async function () { const a = new BigNumber(7000); const b = new BigNumber(5678); - (await this.safeMath.divUints(a, b)).should.be.bignumber.equal(1); + (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); }); - it('reverts on zero division', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); - - await shouldFail.reverting(this.safeMath.divUints(a, b)); - }); - }); - - describe('mod', function () { - describe('modulos correctly', async function () { - it('when the dividend is smaller than the divisor', async function () { - const a = new BigNumber(284); - const b = new BigNumber(5678); - - (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); - }); - - it('when the dividend is equal to the divisor', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(5678); - - (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); - }); - - it('when the dividend is larger than the divisor', async function () { - const a = new BigNumber(7000); - const b = new BigNumber(5678); - - (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); - }); - - it('when the dividend is a multiple of the divisor', async function () { - const a = new BigNumber(17034); // 17034 == 5678 * 3 - const b = new BigNumber(5678); - - (await this.safeMath.modUints(a, b)).should.be.bignumber.equal(a.mod(b)); - }); - }); - - it('reverts with a 0 divisor', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(0); - - await shouldFail.reverting(this.safeMath.modUints(a, b)); - }); - }); - }); - - describe('signed', function () { - describe('add', function () { - it('adds correctly if it does not overflow and the result is positve', async function () { - const a = new BigNumber(1234); + it('when the dividend is a multiple of the divisor', async function () { + const a = new BigNumber(17034); // 17034 == 5678 * 3 const b = new BigNumber(5678); - (await this.safeMath.addUints(a, b)).should.be.bignumber.equal(a.plus(b)); - }); - - it('adds correctly if it does not overflow and the result is negative', async function () { - const a = MAX_INT256; - const b = MIN_INT256; - - const result = await this.safeMath.addInts(a, b); - result.should.be.bignumber.equal(a.plus(b)); - }); - - it('reverts on positive addition overflow', async function () { - const a = MAX_INT256; - const b = new BigNumber(1); - - await shouldFail.reverting(this.safeMath.addInts(a, b)); - }); - - it('reverts on negative addition overflow', async function () { - const a = MIN_INT256; - const b = new BigNumber(-1); - - await shouldFail.reverting(this.safeMath.addInts(a, b)); + (await this.safeMath.mod(a, b)).should.be.bignumber.equal(a.mod(b)); }); }); - describe('sub', function () { - it('subtracts correctly if it does not overflow and the result is positive', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(1234); + it('reverts with a 0 divisor', async function () { + const a = new BigNumber(5678); + const b = new BigNumber(0); - const result = await this.safeMath.subInts(a, b); - result.should.be.bignumber.equal(a.minus(b)); - }); - - it('subtracts correctly if it does not overflow and the result is negative', async function () { - const a = new BigNumber(1234); - const b = new BigNumber(5678); - - const result = await this.safeMath.subInts(a, b); - result.should.be.bignumber.equal(a.minus(b)); - }); - - it('reverts on positive subtraction overflow', async function () { - const a = MAX_INT256; - const b = new BigNumber(-1); - - await shouldFail.reverting(this.safeMath.subInts(a, b)); - }); - - it('reverts on negative subtraction overflow', async function () { - const a = MIN_INT256; - const b = new BigNumber(1); - - await shouldFail.reverting(this.safeMath.subInts(a, b)); - }); - }); - - describe('mul', function () { - it('multiplies correctly', async function () { - const a = new BigNumber(5678); - const b = new BigNumber(-1234); - - const result = await this.safeMath.mulInts(a, b); - result.should.be.bignumber.equal(a.times(b)); - }); - - it('handles a zero product correctly', async function () { - const a = new BigNumber(0); - const b = new BigNumber(5678); - - const result = await this.safeMath.mulInts(a, b); - result.should.be.bignumber.equal(a.times(b)); - }); - - it('reverts on multiplication overflow, positive operands', async function () { - const a = MAX_INT256; - const b = new BigNumber(2); - - await shouldFail.reverting(this.safeMath.mulInts(a, b)); - }); - - it('reverts when minimum integer is multiplied by -1', async function () { - const a = MIN_INT256; - const b = new BigNumber(-1); - - await shouldFail.reverting(this.safeMath.mulInts(a, b)); - }); - - it('reverts when -1 is multiplied by minimum integer', async function () { - const a = new BigNumber(-1); - const b = MIN_INT256; - - await shouldFail.reverting(this.safeMath.mulInts(a, b)); - }); - }); - - describe('div', function () { - it('divides correctly', async function () { - const a = new BigNumber(-5678); - const b = new BigNumber(5678); - - const result = await this.safeMath.divInts(a, b); - result.should.be.bignumber.equal(a.div(b)); - }); - - it('reverts on zero division', async function () { - const a = new BigNumber(-5678); - const b = new BigNumber(0); - - await shouldFail.reverting(this.safeMath.divInts(a, b)); - }); - - it('reverts on overflow, negative second', async function () { - const a = new BigNumber(MIN_INT256); - const b = new BigNumber(-1); - - await shouldFail.reverting(this.safeMath.divInts(a, b)); - }); + await shouldFail.reverting(this.safeMath.mod(a, b)); }); }); }); From 35d70397b64e0b92a0e90da1e1ecb984da1797ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 15:32:24 -0300 Subject: [PATCH 199/205] Rename WhitelisterRole to WhitelistAdminRole. (#1589) * Rename WhitelisterRole to WhitelistAdminRole. * Update WhitelistAdmin changelog entry. --- CHANGELOG.md | 2 +- contracts/access/roles/WhitelistAdminRole.sol | 47 +++++++++++++++++++ contracts/access/roles/WhitelistedRole.sol | 14 +++--- contracts/access/roles/WhitelisterRole.sol | 47 ------------------- contracts/mocks/WhitelistAdminRoleMock.sol | 17 +++++++ contracts/mocks/WhitelisterRoleMock.sol | 17 ------- test/access/roles/WhitelistAdminRole.test.js | 11 +++++ test/access/roles/WhitelistedRole.test.js | 10 ++-- test/access/roles/WhitelisterRole.test.js | 11 ----- 9 files changed, 88 insertions(+), 88 deletions(-) create mode 100644 contracts/access/roles/WhitelistAdminRole.sol delete mode 100644 contracts/access/roles/WhitelisterRole.sol create mode 100644 contracts/mocks/WhitelistAdminRoleMock.sol delete mode 100644 contracts/mocks/WhitelisterRoleMock.sol create mode 100644 test/access/roles/WhitelistAdminRole.test.js delete mode 100644 test/access/roles/WhitelisterRole.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 03974ab30..c54750b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### New features: * Now targeting the 0.5.x line of Solidity compilers. For 0.4.24 support, use version 2.0 of OpenZeppelin. - * `WhitelistCrowdsale`: a crowdsale where only whitelisted accounts (`WhitelistedRole`) can purchase tokens. Adding or removing accounts from the whitelist is done by whitelisters (`WhitelisterRole`). Similar to the pre-2.0 `WhitelistedCrowdsale`. ([#1525](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1525)) + * `WhitelistCrowdsale`: a crowdsale where only whitelisted accounts (`WhitelistedRole`) can purchase tokens. Adding or removing accounts from the whitelist is done by whitelist admins (`WhitelistAdminRole`). Similar to the pre-2.0 `WhitelistedCrowdsale`. ([#1525](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1525), [#1589](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1589)) * `RefundablePostDeliveryCrowdsale`: replacement for `RefundableCrowdsale` (deprecated, see below) where tokens are only granted once the crowdsale ends (if it meets its goal). ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543)) * `PausableCrowdsale`: allows for pausers (`PauserRole`) to pause token purchases. Other crowdsale operations (e.g. withdrawals and refunds, if applicable) are not affected. ([#832](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/832)) * `ERC20`: `transferFrom` and `_burnFrom ` now emit `Approval` events, to represent the token's state comprehensively through events. ([#1524](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1524)) diff --git a/contracts/access/roles/WhitelistAdminRole.sol b/contracts/access/roles/WhitelistAdminRole.sol new file mode 100644 index 000000000..8af7412ba --- /dev/null +++ b/contracts/access/roles/WhitelistAdminRole.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.5.0; + +import "../Roles.sol"; + +/** + * @title WhitelistAdminRole + * @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts. + */ +contract WhitelistAdminRole { + using Roles for Roles.Role; + + event WhitelistAdminAdded(address indexed account); + event WhitelistAdminRemoved(address indexed account); + + Roles.Role private _whitelistAdmins; + + constructor () internal { + _addWhitelistAdmin(msg.sender); + } + + modifier onlyWhitelistAdmin() { + require(isWhitelistAdmin(msg.sender)); + _; + } + + function isWhitelistAdmin(address account) public view returns (bool) { + return _whitelistAdmins.has(account); + } + + function addWhitelistAdmin(address account) public onlyWhitelistAdmin { + _addWhitelistAdmin(account); + } + + function renounceWhitelistAdmin() public { + _removeWhitelistAdmin(msg.sender); + } + + function _addWhitelistAdmin(address account) internal { + _whitelistAdmins.add(account); + emit WhitelistAdminAdded(account); + } + + function _removeWhitelistAdmin(address account) internal { + _whitelistAdmins.remove(account); + emit WhitelistAdminRemoved(account); + } +} diff --git a/contracts/access/roles/WhitelistedRole.sol b/contracts/access/roles/WhitelistedRole.sol index 040d4db58..3ba5ae0cf 100644 --- a/contracts/access/roles/WhitelistedRole.sol +++ b/contracts/access/roles/WhitelistedRole.sol @@ -1,15 +1,15 @@ pragma solidity ^0.5.0; import "../Roles.sol"; -import "./WhitelisterRole.sol"; +import "./WhitelistAdminRole.sol"; /** * @title WhitelistedRole - * @dev Whitelisted accounts have been approved by a Whitelister to perform certain actions (e.g. participate in a - * crowdsale). This role is special in that the only accounts that can add it are Whitelisters (who can also remove it), - * and not Whitelisteds themselves. + * @dev Whitelisted accounts have been approved by a WhitelistAdmin to perform certain actions (e.g. participate in a + * crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove + * it), and not Whitelisteds themselves. */ -contract WhitelistedRole is WhitelisterRole { +contract WhitelistedRole is WhitelistAdminRole { using Roles for Roles.Role; event WhitelistedAdded(address indexed account); @@ -26,11 +26,11 @@ contract WhitelistedRole is WhitelisterRole { return _whitelisteds.has(account); } - function addWhitelisted(address account) public onlyWhitelister { + function addWhitelisted(address account) public onlyWhitelistAdmin { _addWhitelisted(account); } - function removeWhitelisted(address account) public onlyWhitelister { + function removeWhitelisted(address account) public onlyWhitelistAdmin { _removeWhitelisted(account); } diff --git a/contracts/access/roles/WhitelisterRole.sol b/contracts/access/roles/WhitelisterRole.sol deleted file mode 100644 index 8812db6ed..000000000 --- a/contracts/access/roles/WhitelisterRole.sol +++ /dev/null @@ -1,47 +0,0 @@ -pragma solidity ^0.5.0; - -import "../Roles.sol"; - -/** - * @title WhitelisterRole - * @dev Whitelisters are responsible for assigning and removing Whitelisted accounts. - */ -contract WhitelisterRole { - using Roles for Roles.Role; - - event WhitelisterAdded(address indexed account); - event WhitelisterRemoved(address indexed account); - - Roles.Role private _whitelisters; - - constructor () internal { - _addWhitelister(msg.sender); - } - - modifier onlyWhitelister() { - require(isWhitelister(msg.sender)); - _; - } - - function isWhitelister(address account) public view returns (bool) { - return _whitelisters.has(account); - } - - function addWhitelister(address account) public onlyWhitelister { - _addWhitelister(account); - } - - function renounceWhitelister() public { - _removeWhitelister(msg.sender); - } - - function _addWhitelister(address account) internal { - _whitelisters.add(account); - emit WhitelisterAdded(account); - } - - function _removeWhitelister(address account) internal { - _whitelisters.remove(account); - emit WhitelisterRemoved(account); - } -} diff --git a/contracts/mocks/WhitelistAdminRoleMock.sol b/contracts/mocks/WhitelistAdminRoleMock.sol new file mode 100644 index 000000000..5d07f0c40 --- /dev/null +++ b/contracts/mocks/WhitelistAdminRoleMock.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.5.0; + +import "../access/roles/WhitelistAdminRole.sol"; + +contract WhitelistAdminRoleMock is WhitelistAdminRole { + function removeWhitelistAdmin(address account) public { + _removeWhitelistAdmin(account); + } + + function onlyWhitelistAdminMock() public view onlyWhitelistAdmin { + } + + // Causes a compilation error if super._removeWhitelistAdmin is not internal + function _removeWhitelistAdmin(address account) internal { + super._removeWhitelistAdmin(account); + } +} diff --git a/contracts/mocks/WhitelisterRoleMock.sol b/contracts/mocks/WhitelisterRoleMock.sol deleted file mode 100644 index 714410410..000000000 --- a/contracts/mocks/WhitelisterRoleMock.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.0; - -import "../access/roles/WhitelisterRole.sol"; - -contract WhitelisterRoleMock is WhitelisterRole { - function removeWhitelister(address account) public { - _removeWhitelister(account); - } - - function onlyWhitelisterMock() public view onlyWhitelister { - } - - // Causes a compilation error if super._removeWhitelister is not internal - function _removeWhitelister(address account) internal { - super._removeWhitelister(account); - } -} diff --git a/test/access/roles/WhitelistAdminRole.test.js b/test/access/roles/WhitelistAdminRole.test.js new file mode 100644 index 000000000..e59dcd895 --- /dev/null +++ b/test/access/roles/WhitelistAdminRole.test.js @@ -0,0 +1,11 @@ +const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); +const WhitelistAdminRoleMock = artifacts.require('WhitelistAdminRoleMock'); + +contract('WhitelistAdminRole', function ([_, whitelistAdmin, otherWhitelistAdmin, ...otherAccounts]) { + beforeEach(async function () { + this.contract = await WhitelistAdminRoleMock.new({ from: whitelistAdmin }); + await this.contract.addWhitelistAdmin(otherWhitelistAdmin, { from: whitelistAdmin }); + }); + + shouldBehaveLikePublicRole(whitelistAdmin, otherWhitelistAdmin, otherAccounts, 'whitelistAdmin'); +}); diff --git a/test/access/roles/WhitelistedRole.test.js b/test/access/roles/WhitelistedRole.test.js index 2290424cd..e578f6fa2 100644 --- a/test/access/roles/WhitelistedRole.test.js +++ b/test/access/roles/WhitelistedRole.test.js @@ -1,12 +1,12 @@ const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); const WhitelistedRoleMock = artifacts.require('WhitelistedRoleMock'); -contract('WhitelistedRole', function ([_, whitelisted, otherWhitelisted, whitelister, ...otherAccounts]) { +contract('WhitelistedRole', function ([_, whitelisted, otherWhitelisted, whitelistAdmin, ...otherAccounts]) { beforeEach(async function () { - this.contract = await WhitelistedRoleMock.new({ from: whitelister }); - await this.contract.addWhitelisted(whitelisted, { from: whitelister }); - await this.contract.addWhitelisted(otherWhitelisted, { from: whitelister }); + this.contract = await WhitelistedRoleMock.new({ from: whitelistAdmin }); + await this.contract.addWhitelisted(whitelisted, { from: whitelistAdmin }); + await this.contract.addWhitelisted(otherWhitelisted, { from: whitelistAdmin }); }); - shouldBehaveLikePublicRole(whitelisted, otherWhitelisted, otherAccounts, 'whitelisted', whitelister); + shouldBehaveLikePublicRole(whitelisted, otherWhitelisted, otherAccounts, 'whitelisted', whitelistAdmin); }); diff --git a/test/access/roles/WhitelisterRole.test.js b/test/access/roles/WhitelisterRole.test.js deleted file mode 100644 index 39e664407..000000000 --- a/test/access/roles/WhitelisterRole.test.js +++ /dev/null @@ -1,11 +0,0 @@ -const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior'); -const WhitelisterRoleMock = artifacts.require('WhitelisterRoleMock'); - -contract('WhitelisterRole', function ([_, whitelister, otherWhitelister, ...otherAccounts]) { - beforeEach(async function () { - this.contract = await WhitelisterRoleMock.new({ from: whitelister }); - await this.contract.addWhitelister(otherWhitelister, { from: whitelister }); - }); - - shouldBehaveLikePublicRole(whitelister, otherWhitelister, otherAccounts, 'whitelister'); -}); From 76abd1a41ec7d96ef76370f3eadfe097226896a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 17:01:52 -0300 Subject: [PATCH 200/205] Replaced Solium in favor of Solhint (#1575) * Adding solhint, working on style fixes. * Upgraded to solhint 1.5.0. * Removed all references to Solium * Updated mocks to make the pass the new linter rules. * Reformatted the .solhint.json file a bit. * Removed Solium configuration files. * Remove Solium dependency. * Add comment explaing disabled time rule in TokenVesting. * Revert to the old (ugly?) style. * Revert SignatureBouncerMock style. * Fix ERC165InterfacesSupported interface. --- .solhint.json | 11 + .soliumignore | 1 - .soliumrc.json | 22 - contracts/crowdsale/Crowdsale.sol | 27 +- .../distribution/FinalizableCrowdsale.sol | 4 +- .../price/IncreasingPriceCrowdsale.sol | 2 +- .../validation/PausableCrowdsale.sol | 4 +- .../crowdsale/validation/TimedCrowdsale.sol | 6 +- contracts/cryptography/ECDSA.sol | 3 +- contracts/drafts/ERC1046/TokenMetadata.sol | 1 - contracts/drafts/SignatureBouncer.sol | 4 +- contracts/drafts/TokenVesting.sol | 9 +- contracts/examples/SampleCrowdsale.sol | 9 +- contracts/introspection/ERC165.sol | 4 +- contracts/introspection/ERC165Checker.sol | 18 +- contracts/mocks/AllowanceCrowdsaleImpl.sol | 4 +- contracts/mocks/CappedCrowdsaleImpl.sol | 4 +- contracts/mocks/CapperRoleMock.sol | 1 + contracts/mocks/CrowdsaleMock.sol | 4 +- contracts/mocks/DetailedERC20Mock.sol | 7 +- .../ERC165/ERC165InterfacesSupported.sol | 7 +- contracts/mocks/ERC165/ERC165NotSupported.sol | 4 +- contracts/mocks/ERC20MintableMock.sol | 1 + contracts/mocks/ERC20WithMetadataMock.sol | 4 +- contracts/mocks/ERC721FullMock.sol | 4 +- .../mocks/ERC721MintableBurnableImpl.sol | 4 +- contracts/mocks/ERC721ReceiverMock.sol | 4 +- contracts/mocks/Failer.sol | 1 + contracts/mocks/FinalizableCrowdsaleImpl.sol | 5 +- .../mocks/IncreasingPriceCrowdsaleImpl.sol | 4 +- .../mocks/IndividuallyCappedCrowdsaleImpl.sol | 5 +- contracts/mocks/MintedCrowdsaleImpl.sol | 4 +- contracts/mocks/MinterRoleMock.sol | 1 + contracts/mocks/OwnableMock.sol | 4 +- contracts/mocks/PausableCrowdsaleImpl.sol | 1 + contracts/mocks/PauserRoleMock.sol | 1 + contracts/mocks/PostDeliveryCrowdsaleImpl.sol | 4 +- contracts/mocks/PullPaymentMock.sol | 4 +- contracts/mocks/ReentrancyAttack.sol | 4 +- contracts/mocks/ReentrancyMock.sol | 2 +- contracts/mocks/RefundableCrowdsaleImpl.sol | 4 +- .../RefundablePostDeliveryCrowdsaleImpl.sol | 4 +- contracts/mocks/SafeERC20Helper.sol | 4 - contracts/mocks/SecondaryMock.sol | 4 +- contracts/mocks/SignatureBouncerMock.sol | 38 +- contracts/mocks/SignerRoleMock.sol | 1 + contracts/mocks/TimedCrowdsaleImpl.sol | 4 +- contracts/mocks/WhitelistAdminRoleMock.sol | 1 + contracts/mocks/WhitelistCrowdsaleImpl.sol | 4 +- contracts/mocks/WhitelistedRoleMock.sol | 1 + contracts/payment/escrow/RefundEscrow.sol | 5 +- contracts/token/ERC20/ERC20.sol | 3 +- contracts/token/ERC20/ERC20Pausable.sol | 2 +- contracts/token/ERC20/IERC20.sol | 12 +- contracts/token/ERC20/TokenTimelock.sol | 4 +- contracts/token/ERC721/ERC721.sol | 13 +- contracts/token/ERC721/ERC721Enumerable.sol | 4 +- contracts/token/ERC721/ERC721Full.sol | 4 +- contracts/token/ERC721/ERC721Metadata.sol | 4 +- contracts/token/ERC721/IERC721Full.sol | 1 + contracts/token/ERC721/IERC721Receiver.sol | 3 +- contracts/utils/Address.sol | 2 +- package-lock.json | 1360 +++++++---------- package.json | 11 +- 64 files changed, 787 insertions(+), 919 deletions(-) create mode 100644 .solhint.json delete mode 100644 .soliumignore delete mode 100644 .soliumrc.json diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 000000000..7a85f3cf2 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,11 @@ +{ + "extends": "default", + "rules": { + "indent": ["error", 4], + + "bracket-align": false, + "compiler-fixed": false, + "no-simple-event-func-name": false, + "two-lines-top-level-separator": false + } +} diff --git a/.soliumignore b/.soliumignore deleted file mode 100644 index 3c3629e64..000000000 --- a/.soliumignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/.soliumrc.json b/.soliumrc.json deleted file mode 100644 index e7f413f9f..000000000 --- a/.soliumrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": "solium:all", - "plugins": ["security"], - "rules": { - "arg-overflow": "off", - "blank-lines": "off", - "error-reason": "off", - "indentation": ["error", 4], - "lbrace": "off", - "linebreak-style": ["error", "unix"], - "max-len": ["error", 120], - "no-constant": ["error"], - "no-empty-blocks": "off", - "quotes": ["error", "double"], - "uppercase": "off", - "visibility-first": "error", - - "security/enforce-explicit-visibility": ["error"], - "security/no-block-members": ["warning"], - "security/no-inline-assembly": ["warning"] - } -} diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index 3e188b447..fab17d181 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -63,10 +63,6 @@ contract Crowdsale is ReentrancyGuard { _token = token; } - // ----------------------------------------- - // Crowdsale external interface - // ----------------------------------------- - /** * @dev fallback function ***DO NOT OVERRIDE*** * Note that other contracts will transfer fund with a base gas stipend @@ -130,12 +126,9 @@ contract Crowdsale is ReentrancyGuard { _postValidatePurchase(beneficiary, weiAmount); } - // ----------------------------------------- - // Internal interface (extensible) - // ----------------------------------------- - /** - * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations. + * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. + * Use `super` in contracts that inherit from Crowdsale to extend their validations. * Example from CappedCrowdsale.sol's _preValidatePurchase method: * super._preValidatePurchase(beneficiary, weiAmount); * require(weiRaised().add(weiAmount) <= cap); @@ -148,16 +141,18 @@ contract Crowdsale is ReentrancyGuard { } /** - * @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met. + * @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid + * conditions are not met. * @param beneficiary Address performing the token purchase * @param weiAmount Value in wei involved in the purchase */ function _postValidatePurchase(address beneficiary, uint256 weiAmount) internal view { - // optional override + // solhint-disable-previous-line no-empty-blocks } /** - * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens. + * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends + * its tokens. * @param beneficiary Address performing the token purchase * @param tokenAmount Number of tokens to be emitted */ @@ -166,7 +161,8 @@ contract Crowdsale is ReentrancyGuard { } /** - * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens. + * @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send + * tokens. * @param beneficiary Address receiving the tokens * @param tokenAmount Number of tokens to be purchased */ @@ -175,12 +171,13 @@ contract Crowdsale is ReentrancyGuard { } /** - * @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.) + * @dev Override for extensions that require an internal state to check for validity (current user contributions, + * etc.) * @param beneficiary Address receiving the tokens * @param weiAmount Value in wei involved in the purchase */ function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal { - // optional override + // solhint-disable-previous-line no-empty-blocks } /** diff --git a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol index 7573a3e9a..f904e226f 100644 --- a/contracts/crowdsale/distribution/FinalizableCrowdsale.sol +++ b/contracts/crowdsale/distribution/FinalizableCrowdsale.sol @@ -45,5 +45,7 @@ contract FinalizableCrowdsale is TimedCrowdsale { * should call super._finalization() to ensure the chain of finalization is * executed entirely. */ - function _finalization() internal {} + function _finalization() internal { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol index 51e946c7d..941cfe061 100644 --- a/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol +++ b/contracts/crowdsale/price/IncreasingPriceCrowdsale.sol @@ -59,7 +59,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale { return 0; } - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time uint256 elapsedTime = block.timestamp.sub(openingTime()); uint256 timeRange = closingTime().sub(openingTime()); uint256 rateRange = _initialRate.sub(_finalRate); diff --git a/contracts/crowdsale/validation/PausableCrowdsale.sol b/contracts/crowdsale/validation/PausableCrowdsale.sol index 9d034e096..cc89aebab 100644 --- a/contracts/crowdsale/validation/PausableCrowdsale.sol +++ b/contracts/crowdsale/validation/PausableCrowdsale.sol @@ -8,9 +8,9 @@ import "../../lifecycle/Pausable.sol"; * @dev Extension of Crowdsale contract where purchases can be paused and unpaused by the pauser role. */ contract PausableCrowdsale is Crowdsale, Pausable { - /** - * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations. + * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. + * Use super to concatenate validations. * Adds the validation that the crowdsale must not be paused. * @param _beneficiary Address performing the token purchase * @param _weiAmount Value in wei involved in the purchase diff --git a/contracts/crowdsale/validation/TimedCrowdsale.sol b/contracts/crowdsale/validation/TimedCrowdsale.sol index 418df3bcb..a67206696 100644 --- a/contracts/crowdsale/validation/TimedCrowdsale.sol +++ b/contracts/crowdsale/validation/TimedCrowdsale.sol @@ -27,7 +27,7 @@ contract TimedCrowdsale is Crowdsale { * @param closingTime Crowdsale closing time */ constructor (uint256 openingTime, uint256 closingTime) public { - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time require(openingTime >= block.timestamp); require(closingTime > openingTime); @@ -53,7 +53,7 @@ contract TimedCrowdsale is Crowdsale { * @return true if the crowdsale is open, false otherwise. */ function isOpen() public view returns (bool) { - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time return block.timestamp >= _openingTime && block.timestamp <= _closingTime; } @@ -62,7 +62,7 @@ contract TimedCrowdsale is Crowdsale { * @return Whether crowdsale period has elapsed */ function hasClosed() public view returns (bool) { - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time return block.timestamp > _closingTime; } diff --git a/contracts/cryptography/ECDSA.sol b/contracts/cryptography/ECDSA.sol index be7bc3d55..432a23c9a 100644 --- a/contracts/cryptography/ECDSA.sol +++ b/contracts/cryptography/ECDSA.sol @@ -26,7 +26,7 @@ library ECDSA { // Divide the signature in r, s and v variables // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. - // solium-disable-next-line security/no-inline-assembly + // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) @@ -42,7 +42,6 @@ library ECDSA { if (v != 27 && v != 28) { return (address(0)); } else { - // solium-disable-next-line arg-overflow return ecrecover(hash, v, r, s); } } diff --git a/contracts/drafts/ERC1046/TokenMetadata.sol b/contracts/drafts/ERC1046/TokenMetadata.sol index 1569d1b00..6b00d62fc 100644 --- a/contracts/drafts/ERC1046/TokenMetadata.sol +++ b/contracts/drafts/ERC1046/TokenMetadata.sol @@ -6,7 +6,6 @@ import "../../token/ERC20/IERC20.sol"; * @title ERC-1047 Token Metadata * @dev See https://eips.ethereum.org/EIPS/eip-1046 * @dev tokenURI must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047 - * @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/IERC721.sol#L17 when 1046 is finalized */ contract ERC20TokenMetadata is IERC20 { function tokenURI() external view returns (string memory); diff --git a/contracts/drafts/SignatureBouncer.sol b/contracts/drafts/SignatureBouncer.sol index f0d6f29ca..a5ec7f712 100644 --- a/contracts/drafts/SignatureBouncer.sol +++ b/contracts/drafts/SignatureBouncer.sol @@ -43,7 +43,9 @@ contract SignatureBouncer is SignerRole { // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes uint256 private constant _SIGNATURE_SIZE = 96; - constructor () internal {} + constructor () internal { + // solhint-disable-previous-line no-empty-blocks + } /** * @dev requires that a valid signature of a signer was provided diff --git a/contracts/drafts/TokenVesting.sol b/contracts/drafts/TokenVesting.sol index 6c6f34a11..3b42df82c 100644 --- a/contracts/drafts/TokenVesting.sol +++ b/contracts/drafts/TokenVesting.sol @@ -1,5 +1,3 @@ -/* solium-disable security/no-block-members */ - pragma solidity ^0.5.0; import "../token/ERC20/SafeERC20.sol"; @@ -13,6 +11,12 @@ import "../math/SafeMath.sol"; * owner. */ contract TokenVesting is Ownable { + // The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and is + // therefore sensitive to timestamp manipulation (which is something miners can do, to a certain degree). Therefore, + // it is recommended to avoid using short time durations (less than a minute). Typical vesting schemes, with a cliff + // period of a year and a duration of four years, are safe to use. + // solhint-disable not-rely-on-time + using SafeMath for uint256; using SafeERC20 for IERC20; @@ -22,6 +26,7 @@ contract TokenVesting is Ownable { // beneficiary of tokens after they are released address private _beneficiary; + // Durations and timestamps are expressed in UNIX time, the same units as block.timestamp. uint256 private _cliff; uint256 private _start; uint256 private _duration; diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index b120e88c6..674f2c22e 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -12,7 +12,9 @@ import "../token/ERC20/ERC20Detailed.sol"; * It is meant to be used in a crowdsale contract. */ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { - constructor () public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {} + constructor () public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) { + // solhint-disable-previous-line no-empty-blocks + } } /** @@ -28,11 +30,6 @@ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed { * After adding multiple features it's good practice to run integration tests * to ensure that subcontracts works together as intended. */ -// XXX There doesn't seem to be a way to split this line that keeps solium -// happy. See: -// https://github.com/duaraghav8/Solium/issues/205 -// --elopio - 2018-05-10 -// solium-disable-next-line max-len contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale { constructor ( uint256 openingTime, diff --git a/contracts/introspection/ERC165.sol b/contracts/introspection/ERC165.sol index 8903be17f..9b57ba2fc 100644 --- a/contracts/introspection/ERC165.sol +++ b/contracts/introspection/ERC165.sol @@ -8,7 +8,7 @@ import "./IERC165.sol"; * @dev Implements ERC165 using a lookup table. */ contract ERC165 is IERC165 { - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; + bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) @@ -24,7 +24,7 @@ contract ERC165 is IERC165 { * implement ERC165 itself */ constructor () internal { - _registerInterface(_InterfaceId_ERC165); + _registerInterface(_INTERFACE_ID_ERC165); } /** diff --git a/contracts/introspection/ERC165Checker.sol b/contracts/introspection/ERC165Checker.sol index 6a0fb9ff6..f6034d483 100644 --- a/contracts/introspection/ERC165Checker.sol +++ b/contracts/introspection/ERC165Checker.sol @@ -7,9 +7,9 @@ pragma solidity ^0.5.0; */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff - bytes4 private constant _InterfaceId_Invalid = 0xffffffff; + bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; + bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) @@ -23,8 +23,8 @@ library ERC165Checker { function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return _supportsERC165Interface(account, _InterfaceId_ERC165) && - !_supportsERC165Interface(account, _InterfaceId_Invalid); + return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && + !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** @@ -94,13 +94,13 @@ library ERC165Checker { * indicates support of the interface with identifier interfaceId, false otherwise */ function _callERC165SupportsInterface(address account, bytes4 interfaceId) - private - view - returns (bool success, bool result) + private + view + returns (bool success, bool result) { - bytes memory encodedParams = abi.encodeWithSelector(_InterfaceId_ERC165,interfaceId); + bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); - // solium-disable-next-line security/no-inline-assembly + // solhint-disable-next-line no-inline-assembly assembly { let encodedParams_data := add(0x20, encodedParams) let encodedParams_size := mload(encodedParams) diff --git a/contracts/mocks/AllowanceCrowdsaleImpl.sol b/contracts/mocks/AllowanceCrowdsaleImpl.sol index 944ec21a6..9c6fdb511 100644 --- a/contracts/mocks/AllowanceCrowdsaleImpl.sol +++ b/contracts/mocks/AllowanceCrowdsaleImpl.sol @@ -8,5 +8,7 @@ contract AllowanceCrowdsaleImpl is AllowanceCrowdsale { public Crowdsale(rate, wallet, token) AllowanceCrowdsale(tokenWallet) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index 4c5811b65..d0c59db4c 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -8,5 +8,7 @@ contract CappedCrowdsaleImpl is CappedCrowdsale { public Crowdsale(rate, wallet, token) CappedCrowdsale(cap) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/CapperRoleMock.sol b/contracts/mocks/CapperRoleMock.sol index 090502068..0090d1ff6 100644 --- a/contracts/mocks/CapperRoleMock.sol +++ b/contracts/mocks/CapperRoleMock.sol @@ -8,6 +8,7 @@ contract CapperRoleMock is CapperRole { } function onlyCapperMock() public view onlyCapper { + // solhint-disable-previous-line no-empty-blocks } // Causes a compilation error if super._removeCapper is not internal diff --git a/contracts/mocks/CrowdsaleMock.sol b/contracts/mocks/CrowdsaleMock.sol index 007f49ee8..6dafa4b7e 100644 --- a/contracts/mocks/CrowdsaleMock.sol +++ b/contracts/mocks/CrowdsaleMock.sol @@ -3,5 +3,7 @@ pragma solidity ^0.5.0; import "../crowdsale/Crowdsale.sol"; contract CrowdsaleMock is Crowdsale { - constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {} + constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/DetailedERC20Mock.sol b/contracts/mocks/DetailedERC20Mock.sol index bd45c34b5..f2761b348 100644 --- a/contracts/mocks/DetailedERC20Mock.sol +++ b/contracts/mocks/DetailedERC20Mock.sol @@ -4,5 +4,10 @@ import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20Detailed.sol"; contract ERC20DetailedMock is ERC20, ERC20Detailed { - constructor (string memory name, string memory symbol, uint8 decimals) ERC20Detailed(name, symbol, decimals) public {} + constructor (string memory name, string memory symbol, uint8 decimals) + public + ERC20Detailed(name, symbol, decimals) + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol index 9eb7060ed..fccf84e69 100644 --- a/contracts/mocks/ERC165/ERC165InterfacesSupported.sol +++ b/contracts/mocks/ERC165/ERC165InterfacesSupported.sol @@ -4,14 +4,15 @@ import "../../introspection/IERC165.sol"; /** * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md#specification - * > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead throw an exception. + * > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead + * throw an exception. * > These operations include [...], LOG0, LOG1, LOG2, [...] * * therefore, because this contract is staticcall'd we need to not emit events (which is how solidity-coverage works) * solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it */ contract SupportsInterfaceWithLookupMock is IERC165 { - bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; + bytes4 public constant INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) @@ -27,7 +28,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 { * implement ERC165 itself */ constructor () public { - _registerInterface(InterfaceId_ERC165); + _registerInterface(INTERFACE_ID_ERC165); } /** diff --git a/contracts/mocks/ERC165/ERC165NotSupported.sol b/contracts/mocks/ERC165/ERC165NotSupported.sol index d77baedf3..d154da33e 100644 --- a/contracts/mocks/ERC165/ERC165NotSupported.sol +++ b/contracts/mocks/ERC165/ERC165NotSupported.sol @@ -1,3 +1,5 @@ pragma solidity ^0.5.0; -contract ERC165NotSupported {} +contract ERC165NotSupported { + // solhint-disable-previous-line no-empty-blocks +} diff --git a/contracts/mocks/ERC20MintableMock.sol b/contracts/mocks/ERC20MintableMock.sol index 3e74e8f92..3ea65ef62 100644 --- a/contracts/mocks/ERC20MintableMock.sol +++ b/contracts/mocks/ERC20MintableMock.sol @@ -4,4 +4,5 @@ import "../token/ERC20/ERC20Mintable.sol"; import "./MinterRoleMock.sol"; contract ERC20MintableMock is ERC20Mintable, MinterRoleMock { + // solhint-disable-previous-line no-empty-blocks } diff --git a/contracts/mocks/ERC20WithMetadataMock.sol b/contracts/mocks/ERC20WithMetadataMock.sol index ea61bd3f3..16b967fc8 100644 --- a/contracts/mocks/ERC20WithMetadataMock.sol +++ b/contracts/mocks/ERC20WithMetadataMock.sol @@ -4,5 +4,7 @@ import "../token/ERC20/ERC20.sol"; import "../drafts/ERC1046/TokenMetadata.sol"; contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { - constructor (string memory tokenURI) public ERC20WithMetadata(tokenURI) {} + constructor (string memory tokenURI) public ERC20WithMetadata(tokenURI) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/ERC721FullMock.sol b/contracts/mocks/ERC721FullMock.sol index a21c59d36..b0f00918b 100644 --- a/contracts/mocks/ERC721FullMock.sol +++ b/contracts/mocks/ERC721FullMock.sol @@ -11,7 +11,9 @@ import "../token/ERC721/ERC721Burnable.sol"; * checking token existence, removal of a token from an address */ contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { - constructor (string memory name, string memory symbol) public ERC721Mintable() ERC721Full(name, symbol) {} + constructor (string memory name, string memory symbol) public ERC721Mintable() ERC721Full(name, symbol) { + // solhint-disable-previous-line no-empty-blocks + } function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); diff --git a/contracts/mocks/ERC721MintableBurnableImpl.sol b/contracts/mocks/ERC721MintableBurnableImpl.sol index 169dc7790..fcb692723 100644 --- a/contracts/mocks/ERC721MintableBurnableImpl.sol +++ b/contracts/mocks/ERC721MintableBurnableImpl.sol @@ -9,5 +9,7 @@ import "../token/ERC721/ERC721Burnable.sol"; * @title ERC721MintableBurnableImpl */ contract ERC721MintableBurnableImpl is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable { - constructor () ERC721Mintable() ERC721Full("Test", "TEST") public {} + constructor () public ERC721Mintable() ERC721Full("Test", "TEST") { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/ERC721ReceiverMock.sol b/contracts/mocks/ERC721ReceiverMock.sol index 0bf650c21..1b4de6737 100644 --- a/contracts/mocks/ERC721ReceiverMock.sol +++ b/contracts/mocks/ERC721ReceiverMock.sol @@ -13,7 +13,9 @@ contract ERC721ReceiverMock is IERC721Receiver { _reverts = reverts; } - function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4) { + function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) + public returns (bytes4) + { require(!_reverts); emit Received(operator, from, tokenId, data, gasleft()); return _retval; diff --git a/contracts/mocks/Failer.sol b/contracts/mocks/Failer.sol index 77bdae0f7..088bc498c 100644 --- a/contracts/mocks/Failer.sol +++ b/contracts/mocks/Failer.sol @@ -4,6 +4,7 @@ contract Failer { uint256[] private array; function dontFail() public pure { + // solhint-disable-previous-line no-empty-blocks } function failWithRevert() public pure { diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 6622d15a5..99f7a255d 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -4,10 +4,11 @@ import "../token/ERC20/IERC20.sol"; import "../crowdsale/distribution/FinalizableCrowdsale.sol"; contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { - constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol index bcb37e9cd..c5b0e7957 100644 --- a/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol +++ b/contracts/mocks/IncreasingPriceCrowdsaleImpl.sol @@ -16,5 +16,7 @@ contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale { Crowdsale(initialRate, wallet, token) TimedCrowdsale(openingTime, closingTime) IncreasingPriceCrowdsale(initialRate, finalRate) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol index 83e8f6e53..43b0366ee 100644 --- a/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol +++ b/contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol @@ -5,6 +5,7 @@ import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol"; import "./CapperRoleMock.sol"; contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock { - constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) - {} + constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/MintedCrowdsaleImpl.sol b/contracts/mocks/MintedCrowdsaleImpl.sol index 16f2a1c02..22f4d36c0 100644 --- a/contracts/mocks/MintedCrowdsaleImpl.sol +++ b/contracts/mocks/MintedCrowdsaleImpl.sol @@ -4,5 +4,7 @@ import "../token/ERC20/ERC20Mintable.sol"; import "../crowdsale/emission/MintedCrowdsale.sol"; contract MintedCrowdsaleImpl is MintedCrowdsale { - constructor (uint256 rate, address payable wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) {} + constructor (uint256 rate, address payable wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/MinterRoleMock.sol b/contracts/mocks/MinterRoleMock.sol index 7e1d7d15d..4b0401d87 100644 --- a/contracts/mocks/MinterRoleMock.sol +++ b/contracts/mocks/MinterRoleMock.sol @@ -8,6 +8,7 @@ contract MinterRoleMock is MinterRole { } function onlyMinterMock() public view onlyMinter { + // solhint-disable-previous-line no-empty-blocks } // Causes a compilation error if super._removeMinter is not internal diff --git a/contracts/mocks/OwnableMock.sol b/contracts/mocks/OwnableMock.sol index f64f8e7a0..c7b1cf5c7 100644 --- a/contracts/mocks/OwnableMock.sol +++ b/contracts/mocks/OwnableMock.sol @@ -2,4 +2,6 @@ pragma solidity ^0.5.0; import "../ownership/Ownable.sol"; -contract OwnableMock is Ownable {} +contract OwnableMock is Ownable { + // solhint-disable-previous-line no-empty-blocks +} diff --git a/contracts/mocks/PausableCrowdsaleImpl.sol b/contracts/mocks/PausableCrowdsaleImpl.sol index 8ac695078..11f44c7b8 100644 --- a/contracts/mocks/PausableCrowdsaleImpl.sol +++ b/contracts/mocks/PausableCrowdsaleImpl.sol @@ -5,5 +5,6 @@ import "../crowdsale/validation/PausableCrowdsale.sol"; contract PausableCrowdsaleImpl is PausableCrowdsale { constructor (uint256 _rate, address payable _wallet, ERC20 _token) public Crowdsale(_rate, _wallet, _token) { + // solhint-disable-previous-line no-empty-blocks } } diff --git a/contracts/mocks/PauserRoleMock.sol b/contracts/mocks/PauserRoleMock.sol index b6dce92b4..fc2ed16d9 100644 --- a/contracts/mocks/PauserRoleMock.sol +++ b/contracts/mocks/PauserRoleMock.sol @@ -8,6 +8,7 @@ contract PauserRoleMock is PauserRole { } function onlyPauserMock() public view onlyPauser { + // solhint-disable-previous-line no-empty-blocks } // Causes a compilation error if super._removePauser is not internal diff --git a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol index b612ac518..efb67c084 100644 --- a/contracts/mocks/PostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/PostDeliveryCrowdsaleImpl.sol @@ -8,5 +8,7 @@ contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale { public TimedCrowdsale(openingTime, closingTime) Crowdsale(rate, wallet, token) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/PullPaymentMock.sol b/contracts/mocks/PullPaymentMock.sol index 1ecddccd3..1a26b6242 100644 --- a/contracts/mocks/PullPaymentMock.sol +++ b/contracts/mocks/PullPaymentMock.sol @@ -4,7 +4,9 @@ import "../payment/PullPayment.sol"; // mock class using PullPayment contract PullPaymentMock is PullPayment { - constructor () public payable { } + constructor () public payable { + // solhint-disable-previous-line no-empty-blocks + } // test helper function to call asyncTransfer function callTransfer(address dest, uint256 amount) public { diff --git a/contracts/mocks/ReentrancyAttack.sol b/contracts/mocks/ReentrancyAttack.sol index a4675f986..965a053e0 100644 --- a/contracts/mocks/ReentrancyAttack.sol +++ b/contracts/mocks/ReentrancyAttack.sol @@ -1,11 +1,9 @@ pragma solidity ^0.5.0; contract ReentrancyAttack { - function callSender(bytes4 data) public { - // solium-disable-next-line security/no-low-level-calls + // solhint-disable-next-line avoid-low-level-calls (bool success,) = msg.sender.call(abi.encodeWithSelector(data)); require(success); } - } diff --git a/contracts/mocks/ReentrancyMock.sol b/contracts/mocks/ReentrancyMock.sol index b314e54f0..a32a40472 100644 --- a/contracts/mocks/ReentrancyMock.sol +++ b/contracts/mocks/ReentrancyMock.sol @@ -24,7 +24,7 @@ contract ReentrancyMock is ReentrancyGuard { function countThisRecursive(uint256 n) public nonReentrant { if (n > 0) { count(); - // solium-disable-next-line security/no-low-level-calls + // solhint-disable-next-line avoid-low-level-calls (bool success,) = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1)); require(success); } diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index 9e466867b..5ed5d1ed5 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -16,5 +16,7 @@ contract RefundableCrowdsaleImpl is RefundableCrowdsale { Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) RefundableCrowdsale(goal) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol index 6772971c8..b81f0757c 100644 --- a/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol +++ b/contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol @@ -16,5 +16,7 @@ contract RefundablePostDeliveryCrowdsaleImpl is RefundablePostDeliveryCrowdsale Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) RefundableCrowdsale(goal) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/SafeERC20Helper.sol b/contracts/mocks/SafeERC20Helper.sol index e374ead8c..c9c455e58 100644 --- a/contracts/mocks/SafeERC20Helper.sol +++ b/contracts/mocks/SafeERC20Helper.sol @@ -58,8 +58,6 @@ contract SafeERC20Helper { _succeeding = IERC20(address(new ERC20SucceedingMock())); } - // Using _failing - function doFailingTransfer() public { _failing.safeTransfer(address(0), 0); } @@ -80,8 +78,6 @@ contract SafeERC20Helper { _failing.safeDecreaseAllowance(address(0), 0); } - // Using _succeeding - function doSucceedingTransfer() public { _succeeding.safeTransfer(address(0), 0); } diff --git a/contracts/mocks/SecondaryMock.sol b/contracts/mocks/SecondaryMock.sol index b20b5c2a0..1ff45b11e 100644 --- a/contracts/mocks/SecondaryMock.sol +++ b/contracts/mocks/SecondaryMock.sol @@ -3,5 +3,7 @@ pragma solidity ^0.5.0; import "../ownership/Secondary.sol"; contract SecondaryMock is Secondary { - function onlyPrimaryMock() public view onlyPrimary {} + function onlyPrimaryMock() public view onlyPrimary { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/SignatureBouncerMock.sol b/contracts/mocks/SignatureBouncerMock.sol index b31fb1986..59c59b437 100644 --- a/contracts/mocks/SignatureBouncerMock.sol +++ b/contracts/mocks/SignatureBouncerMock.sol @@ -4,25 +4,47 @@ import "../drafts/SignatureBouncer.sol"; import "./SignerRoleMock.sol"; contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock { - function checkValidSignature(address account, bytes memory signature) public view returns (bool) { + function checkValidSignature(address account, bytes memory signature) + public view returns (bool) + { return _isValidSignature(account, signature); } - function onlyWithValidSignature(bytes memory signature) public onlyValidSignature(signature) view {} + function onlyWithValidSignature(bytes memory signature) + public onlyValidSignature(signature) view + { + // solhint-disable-previous-line no-empty-blocks + } - function checkValidSignatureAndMethod(address account, bytes memory signature) public view returns (bool) { + function checkValidSignatureAndMethod(address account, bytes memory signature) + public view returns (bool) + { return _isValidSignatureAndMethod(account, signature); } - function onlyWithValidSignatureAndMethod(bytes memory signature) public onlyValidSignatureAndMethod(signature) view {} + function onlyWithValidSignatureAndMethod(bytes memory signature) + public onlyValidSignatureAndMethod(signature) view + { + // solhint-disable-previous-line no-empty-blocks + } - function checkValidSignatureAndData(address account, bytes memory, uint, bytes memory signature) public view returns (bool) { + function checkValidSignatureAndData(address account, bytes memory, uint, bytes memory signature) + public view returns (bool) + { return _isValidSignatureAndData(account, signature); } - function onlyWithValidSignatureAndData(uint, bytes memory signature) public onlyValidSignatureAndData(signature) view {} + function onlyWithValidSignatureAndData(uint, bytes memory signature) + public onlyValidSignatureAndData(signature) view + { + // solhint-disable-previous-line no-empty-blocks + } - function theWrongMethod(bytes memory) public pure {} + function theWrongMethod(bytes memory) public pure { + // solhint-disable-previous-line no-empty-blocks + } - function tooShortMsgData() public onlyValidSignatureAndData("") view {} + function tooShortMsgData() public onlyValidSignatureAndData("") view { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/SignerRoleMock.sol b/contracts/mocks/SignerRoleMock.sol index f9ed2876a..71b4c792a 100644 --- a/contracts/mocks/SignerRoleMock.sol +++ b/contracts/mocks/SignerRoleMock.sol @@ -8,6 +8,7 @@ contract SignerRoleMock is SignerRole { } function onlySignerMock() public view onlySigner { + // solhint-disable-previous-line no-empty-blocks } // Causes a compilation error if super._removeSigner is not internal diff --git a/contracts/mocks/TimedCrowdsaleImpl.sol b/contracts/mocks/TimedCrowdsaleImpl.sol index 63bf24cce..463fdcb88 100644 --- a/contracts/mocks/TimedCrowdsaleImpl.sol +++ b/contracts/mocks/TimedCrowdsaleImpl.sol @@ -8,5 +8,7 @@ contract TimedCrowdsaleImpl is TimedCrowdsale { public Crowdsale(rate, wallet, token) TimedCrowdsale(openingTime, closingTime) - {} + { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/WhitelistAdminRoleMock.sol b/contracts/mocks/WhitelistAdminRoleMock.sol index 5d07f0c40..7a267ca21 100644 --- a/contracts/mocks/WhitelistAdminRoleMock.sol +++ b/contracts/mocks/WhitelistAdminRoleMock.sol @@ -8,6 +8,7 @@ contract WhitelistAdminRoleMock is WhitelistAdminRole { } function onlyWhitelistAdminMock() public view onlyWhitelistAdmin { + // solhint-disable-previous-line no-empty-blocks } // Causes a compilation error if super._removeWhitelistAdmin is not internal diff --git a/contracts/mocks/WhitelistCrowdsaleImpl.sol b/contracts/mocks/WhitelistCrowdsaleImpl.sol index 6682e392e..0200f7f7f 100644 --- a/contracts/mocks/WhitelistCrowdsaleImpl.sol +++ b/contracts/mocks/WhitelistCrowdsaleImpl.sol @@ -6,5 +6,7 @@ import "../crowdsale/Crowdsale.sol"; contract WhitelistCrowdsaleImpl is Crowdsale, WhitelistCrowdsale { - constructor (uint256 _rate, address payable _wallet, IERC20 _token) Crowdsale(_rate, _wallet, _token) public {} + constructor (uint256 _rate, address payable _wallet, IERC20 _token) public Crowdsale(_rate, _wallet, _token) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/mocks/WhitelistedRoleMock.sol b/contracts/mocks/WhitelistedRoleMock.sol index 34761a548..7f7c89412 100644 --- a/contracts/mocks/WhitelistedRoleMock.sol +++ b/contracts/mocks/WhitelistedRoleMock.sol @@ -4,5 +4,6 @@ import "../access/roles/WhitelistedRole.sol"; contract WhitelistedRoleMock is WhitelistedRole { function onlyWhitelistedMock() public view onlyWhitelisted { + // solhint-disable-previous-line no-empty-blocks } } diff --git a/contracts/payment/escrow/RefundEscrow.sol b/contracts/payment/escrow/RefundEscrow.sol index 18c6fd355..0c9cd99a6 100644 --- a/contracts/payment/escrow/RefundEscrow.sol +++ b/contracts/payment/escrow/RefundEscrow.sol @@ -83,9 +83,10 @@ contract RefundEscrow is ConditionalEscrow { } /** - * @dev Returns whether refundees can withdraw their deposits (be refunded). + * @dev Returns whether refundees can withdraw their deposits (be refunded). The overriden function receives a + * 'payee' argument, but we ignore it here since the condition is global, not per-payee. */ - function withdrawalAllowed(address payee) public view returns (bool) { + function withdrawalAllowed(address) public view returns (bool) { return _state == State.Refunding; } } diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 318445fc4..30f9642f8 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -8,7 +8,8 @@ import "../../math/SafeMath.sol"; * * @dev Implementation of the basic standard token. * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md - * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + * Originally based on code by FirstBlood: + * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol * * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for * all accounts just by listening to said events. Note that this isn't required by the specification, and other diff --git a/contracts/token/ERC20/ERC20Pausable.sol b/contracts/token/ERC20/ERC20Pausable.sol index e54228eaa..a27de259d 100644 --- a/contracts/token/ERC20/ERC20Pausable.sol +++ b/contracts/token/ERC20/ERC20Pausable.sol @@ -12,7 +12,7 @@ contract ERC20Pausable is ERC20, Pausable { return super.transfer(to, value); } - function transferFrom(address from,address to, uint256 value) public whenNotPaused returns (bool) { + function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) { return super.transferFrom(from, to, value); } diff --git a/contracts/token/ERC20/IERC20.sol b/contracts/token/ERC20/IERC20.sol index 5ae0a6d93..af4a48558 100644 --- a/contracts/token/ERC20/IERC20.sol +++ b/contracts/token/ERC20/IERC20.sol @@ -5,18 +5,18 @@ pragma solidity ^0.5.0; * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 { - function totalSupply() external view returns (uint256); - - function balanceOf(address who) external view returns (uint256); - - function allowance(address owner, address spender) external view returns (uint256); - function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); + function totalSupply() external view returns (uint256); + + function balanceOf(address who) external view returns (uint256); + + function allowance(address owner, address spender) external view returns (uint256); + event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); diff --git a/contracts/token/ERC20/TokenTimelock.sol b/contracts/token/ERC20/TokenTimelock.sol index f8899d212..fb56a3310 100644 --- a/contracts/token/ERC20/TokenTimelock.sol +++ b/contracts/token/ERC20/TokenTimelock.sol @@ -20,7 +20,7 @@ contract TokenTimelock { uint256 private _releaseTime; constructor (IERC20 token, address beneficiary, uint256 releaseTime) public { - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time require(releaseTime > block.timestamp); _token = token; _beneficiary = beneficiary; @@ -52,7 +52,7 @@ contract TokenTimelock { * @notice Transfers tokens held by timelock to beneficiary. */ function release() public { - // solium-disable-next-line security/no-block-members + // solhint-disable-next-line not-rely-on-time require(block.timestamp >= _releaseTime); uint256 amount = _token.balanceOf(address(this)); diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 6d177e8d9..7c51ce60a 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -30,7 +30,7 @@ contract ERC721 is ERC165, IERC721 { // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; - bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; + bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * 0x80ac58cd === * bytes4(keccak256('balanceOf(address)')) ^ @@ -46,7 +46,7 @@ contract ERC721 is ERC165, IERC721 { constructor () public { // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(_InterfaceId_ERC721); + _registerInterface(_INTERFACE_ID_ERC721); } /** @@ -147,7 +147,6 @@ contract ERC721 is ERC165, IERC721 { * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom(address from, address to, uint256 tokenId) public { - // solium-disable-next-line arg-overflow safeTransferFrom(from, to, tokenId, ""); } @@ -165,7 +164,6 @@ contract ERC721 is ERC165, IERC721 { */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { transferFrom(from, to, tokenId); - // solium-disable-next-line arg-overflow require(_checkOnERC721Received(from, to, tokenId, _data)); } @@ -188,9 +186,6 @@ contract ERC721 is ERC165, IERC721 { */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { address owner = ownerOf(tokenId); - // Disable solium check because of - // https://github.com/duaraghav8/Solium/issues/175 - // solium-disable-next-line operator-whitespace return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } @@ -267,7 +262,9 @@ contract ERC721 is ERC165, IERC721 { * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ - function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { + function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) + internal returns (bool) + { if (!to.isContract()) { return true; } diff --git a/contracts/token/ERC721/ERC721Enumerable.sol b/contracts/token/ERC721/ERC721Enumerable.sol index e1f291ea3..282e9873b 100644 --- a/contracts/token/ERC721/ERC721Enumerable.sol +++ b/contracts/token/ERC721/ERC721Enumerable.sol @@ -21,7 +21,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; - bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; + bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * 0x780e9d63 === * bytes4(keccak256('totalSupply()')) ^ @@ -34,7 +34,7 @@ contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { */ constructor () public { // register the supported interface to conform to ERC721 via ERC165 - _registerInterface(_InterfaceId_ERC721Enumerable); + _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** diff --git a/contracts/token/ERC721/ERC721Full.sol b/contracts/token/ERC721/ERC721Full.sol index 2db57305c..f4e8042c4 100644 --- a/contracts/token/ERC721/ERC721Full.sol +++ b/contracts/token/ERC721/ERC721Full.sol @@ -11,5 +11,7 @@ import "./ERC721Metadata.sol"; * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata { - constructor (string memory name, string memory symbol) ERC721Metadata(name, symbol) public {} + constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) { + // solhint-disable-previous-line no-empty-blocks + } } diff --git a/contracts/token/ERC721/ERC721Metadata.sol b/contracts/token/ERC721/ERC721Metadata.sol index 703d524b2..41593297e 100644 --- a/contracts/token/ERC721/ERC721Metadata.sol +++ b/contracts/token/ERC721/ERC721Metadata.sol @@ -14,7 +14,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; - bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; + bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /** * 0x5b5e139f === * bytes4(keccak256('name()')) ^ @@ -30,7 +30,7 @@ contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 - _registerInterface(InterfaceId_ERC721Metadata); + _registerInterface(_INTERFACE_ID_ERC721_METADATA); } /** diff --git a/contracts/token/ERC721/IERC721Full.sol b/contracts/token/ERC721/IERC721Full.sol index 9779a8204..17f593894 100644 --- a/contracts/token/ERC721/IERC721Full.sol +++ b/contracts/token/ERC721/IERC721Full.sol @@ -9,4 +9,5 @@ import "./IERC721Metadata.sol"; * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Full is IERC721, IERC721Enumerable, IERC721Metadata { + // solhint-disable-previous-line no-empty-blocks } diff --git a/contracts/token/ERC721/IERC721Receiver.sol b/contracts/token/ERC721/IERC721Receiver.sol index 0d13d66a1..e2d019759 100644 --- a/contracts/token/ERC721/IERC721Receiver.sol +++ b/contracts/token/ERC721/IERC721Receiver.sol @@ -20,5 +20,6 @@ contract IERC721Receiver { * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ - function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4); + function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) + public returns (bytes4); } diff --git a/contracts/utils/Address.sol b/contracts/utils/Address.sol index 8b6d4255e..500467212 100644 --- a/contracts/utils/Address.sol +++ b/contracts/utils/Address.sol @@ -19,7 +19,7 @@ library Address { // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. - // solium-disable-next-line security/no-inline-assembly + // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } diff --git a/package-lock.json b/package-lock.json index 7d0594d02..3bfa7a9f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,63 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -152,15 +209,11 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } + "antlr4": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.1.tgz", + "integrity": "sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ==", + "dev": true }, "argparse": { "version": "1.0.10", @@ -255,18 +308,18 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -1531,12 +1584,6 @@ "from": "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", "dev": true }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true - }, "binaryextensions": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", @@ -1831,23 +1878,6 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -2554,6 +2584,13 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "optional": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -2577,12 +2614,6 @@ "tapable": "^1.0.0" } }, - "eol": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", - "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==", - "dev": true - }, "errno": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", @@ -2994,6 +3025,12 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -3016,6 +3053,25 @@ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, + "esprima-extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz", + "integrity": "sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==", + "dev": true, + "optional": true, + "requires": { + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "optional": true + } + } + }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", @@ -3391,6 +3447,17 @@ "is-extglob": "^1.0.0" } }, + "extract-comments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/extract-comments/-/extract-comments-1.1.0.tgz", + "integrity": "sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==", + "dev": true, + "optional": true, + "requires": { + "esprima-extract-comments": "^1.1.0", + "parse-code-context": "^1.0.0" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -3403,6 +3470,12 @@ "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", @@ -3949,7 +4022,7 @@ }, "fs-extra": { "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { @@ -3966,549 +4039,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, "function-bind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", @@ -5259,15 +4789,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, "is-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", @@ -5620,12 +5141,6 @@ "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=", "dev": true }, - "js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", - "dev": true - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -5760,7 +5275,7 @@ }, "jsonfile": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { @@ -6903,6 +6418,13 @@ "p-finally": "^1.0.0" } }, + "parse-code-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-code-context/-/parse-code-context-1.0.0.tgz", + "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", + "dev": true, + "optional": true + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -7094,6 +6616,74 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "prettier": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.3.tgz", + "integrity": "sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg==", + "dev": true, + "optional": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "prettier-plugin-solidity": { + "version": "1.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.12.tgz", + "integrity": "sha512-H5SqMHv1jttrm8h8JwVIm+f3BAXLGvqgxfXioUfPl7x0Rw+3KZaQ53bW2DBpJG7NefJxnUKq5dZrWZkclqp9AA==", + "dev": true, + "optional": true, + "requires": { + "emoji-regex": "^7.0.1", + "escape-string-regexp": "^1.0.5", + "extract-comments": "^1.1.0", + "prettier": "^1.15.2", + "solidity-parser-antlr": "^0.3.1", + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "optional": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "optional": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", @@ -7252,18 +6842,6 @@ "util-deprecate": "~1.0.1" } }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } - }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -7731,12 +7309,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -7960,12 +7532,6 @@ "kind-of": "^3.2.0" } }, - "sol-digger": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/sol-digger/-/sol-digger-0.0.2.tgz", - "integrity": "sha1-QGxKnTHiaef4jrHC6hATGOXgkCU=", - "dev": true - }, "sol-explore": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz", @@ -8009,6 +7575,372 @@ } } }, + "solhint": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-1.5.0.tgz", + "integrity": "sha512-D4vmV9hlBRcBEdCap6kHUKtBOjKJbC6JhvsoGrcTKW6+WHRDkbpif35R1Enzd0+OvvIC2UReMwK85dSqrqUSoQ==", + "dev": true, + "requires": { + "antlr4": "4.7.1", + "commander": "2.18.0", + "eslint": "^5.6.0", + "fast-diff": "^1.1.2", + "glob": "7.1.3", + "ignore": "^4.0.6", + "lodash": "^4.17.11", + "prettier": "^1.14.3", + "prettier-linter-helpers": "^1.0.0", + "prettier-plugin-solidity": "^1.0.0-alpha.4" + }, + "dependencies": { + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, + "ajv": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", + "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "commander": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", + "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.11.0.tgz", + "integrity": "sha512-gbEg0ttToZPkZUv2yYjpipxuYrv/9aSSmgM4V6GkiO3u04QosHYBtduUCqLEulEg3YvNDAkk3OWzyQJ/heZ3Nw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "imurmurhash": "^0.1.4", + "inquirer": "^6.1.0", + "js-yaml": "^3.12.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.0.2", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.0.tgz", + "integrity": "sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", + "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "inquirer": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", + "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "slice-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz", + "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz", + "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==", + "dev": true, + "requires": { + "ajv": "^6.6.1", + "lodash": "^4.17.11", + "slice-ansi": "2.0.0", + "string-width": "^2.1.1" + } + } + } + }, "solidity-coverage": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.5.4.tgz", @@ -8027,6 +7959,13 @@ "web3": "^0.18.4" } }, + "solidity-parser-antlr": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.3.3.tgz", + "integrity": "sha512-RNUc18pjf7DLWs//WF+V+VnvrbetEbNFUYxm2JFbXU62G9WSu+nVyDxV5r+FG4wu8jom17vLdM/3I7bMBGfZ9g==", + "dev": true, + "optional": true + }, "solidity-parser-sc": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/solidity-parser-sc/-/solidity-parser-sc-0.4.10.tgz", @@ -8062,154 +8001,6 @@ } } }, - "solium": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/solium/-/solium-1.1.8.tgz", - "integrity": "sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA==", - "dev": true, - "requires": { - "ajv": "^5.2.2", - "chokidar": "^1.6.0", - "colors": "^1.1.2", - "commander": "^2.9.0", - "eol": "^0.9.1", - "js-string-escape": "^1.0.1", - "lodash": "^4.14.2", - "sol-digger": "0.0.2", - "sol-explore": "1.6.1", - "solium-plugin-security": "0.1.1", - "solparse": "2.2.5", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "sol-explore": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.1.tgz", - "integrity": "sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs=", - "dev": true - }, - "solparse": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/solparse/-/solparse-2.2.5.tgz", - "integrity": "sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA==", - "dev": true, - "requires": { - "mocha": "^4.0.1", - "pegjs": "^0.10.0", - "yargs": "^10.0.3" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", - "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" - } - }, - "yargs-parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", - "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "solium-plugin-security": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz", - "integrity": "sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ==", - "dev": true - }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", @@ -8849,6 +8640,23 @@ "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", "dev": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", diff --git a/package.json b/package.json index 9dcecbc2c..855496221 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,13 @@ "console": "truffle console", "coverage": "scripts/coverage.sh", "lint": "npm run lint:js && npm run lint:sol", - "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", + "lint:fix": "npm run lint:js:fix", "lint:js": "eslint .", "lint:js:fix": "eslint . --fix", - "lint:sol": "solium -d .", - "lint:sol:fix": "solium -d . --fix", + "lint:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\"", "prepack": "npm run build", - "test": "npm run compile && scripts/test.sh", - "version": "scripts/version.js" + "version": "scripts/version.js", + "test": "npm run compile && scripts/test.sh" }, "repository": { "type": "git", @@ -55,8 +54,8 @@ "ethjs-abi": "^0.2.1", "ganache-cli": "6.1.8", "pify": "^4.0.1", + "solhint": "^1.5.0", "solidity-coverage": "^0.5.4", - "solium": "^1.1.8", "truffle": "^4.1.13", "web3-utils": "^1.0.0-beta.34" }, From 6aa88e2b7d530c9090246e61012256654bb5a2c8 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 4 Jan 2019 17:30:45 -0300 Subject: [PATCH 201/205] silence npm output (#1590) --- scripts/compile.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/compile.sh b/scripts/compile.sh index 7de7b6ca0..d037daac5 100755 --- a/scripts/compile.sh +++ b/scripts/compile.sh @@ -12,7 +12,7 @@ rm -rf build/ mkdir -p "$SOLC_05_DIR" cd "$SOLC_05_DIR" -npm init --yes +echo '{ "private": true }' > package.json npm install --save-dev truffle@5.0.0 rm -rf contracts From 312a2584e87d8533fbbd8b38fe112898b11b326f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 17:39:32 -0300 Subject: [PATCH 202/205] Updated 2.1 release date. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c54750b06..6a04d51ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2.1.0 (unreleased) +## 2.1.0 (2019-04-01) ### New features: * Now targeting the 0.5.x line of Solidity compilers. For 0.4.24 support, use version 2.0 of OpenZeppelin. From 4f5715bbd718d518dc990ecfbfcd3be1cf42b59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 17:39:42 -0300 Subject: [PATCH 203/205] Release v2.1.0 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index 5c3c06fb3..7120b9c25 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.1.0-rc.2", + "version": "2.1.0", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index 3bfa7a9f6..1ef2ae809 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0-rc.2", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 855496221..d403e9f27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0-rc.2", + "version": "2.1.0", "description": "Secure Smart Contract library for Solidity", "files": [ "build", From ba83239dd8bf54e61e8b45fbc1523598ae03bf39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 18:40:27 -0300 Subject: [PATCH 204/205] Added 2.1.1 changelog entry. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a04d51ab..da3a89043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 2.1.1 (2019-04-01) + * Version bump to avoid conflict in the npm registry. + ## 2.1.0 (2019-04-01) ### New features: From ae02103e47af2df8471bfd11bc171d5b53cd022c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 4 Jan 2019 18:40:49 -0300 Subject: [PATCH 205/205] Release v2.1.1 --- ethpm.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethpm.json b/ethpm.json index 7120b9c25..03149be3d 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "zeppelin", - "version": "2.1.0", + "version": "2.1.1", "description": "Secure Smart Contract library for Solidity", "authors": [ "OpenZeppelin Community " diff --git a/package-lock.json b/package-lock.json index 1ef2ae809..987840c10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d403e9f27..cded213a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "2.1.0", + "version": "2.1.1", "description": "Secure Smart Contract library for Solidity", "files": [ "build",