aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml9
-rw-r--r--.gitignore4
-rw-r--r--.prettierignore4
-rw-r--r--CODEOWNERS2
-rw-r--r--contracts/TESTING.md48
-rw-r--r--contracts/core/README.md53
-rw-r--r--contracts/core/compiler.json5
-rw-r--r--contracts/core/contracts/examples/Wallet/Wallet.sol2
-rw-r--r--contracts/core/contracts/examples/Whitelist/Whitelist.sol2
-rw-r--r--contracts/core/contracts/extensions/DutchAuction/DutchAuction.sol205
-rw-r--r--contracts/core/contracts/extensions/Forwarder/MixinAssets.sol4
-rw-r--r--contracts/core/contracts/extensions/Forwarder/MixinForwarderCore.sol2
-rw-r--r--contracts/core/contracts/extensions/Forwarder/libs/LibConstants.sol2
-rw-r--r--contracts/core/contracts/extensions/OrderValidator/OrderValidator.sol2
-rw-r--r--contracts/core/contracts/protocol/AssetProxy/MixinAuthorizable.sol2
-rw-r--r--contracts/core/contracts/protocol/AssetProxy/interfaces/IAuthorizable.sol2
-rw-r--r--contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol4
-rw-r--r--contracts/core/contracts/protocol/Exchange/MixinAssetProxyDispatcher.sol2
-rw-r--r--contracts/core/contracts/protocol/Exchange/MixinExchangeCore.sol2
-rw-r--r--contracts/core/contracts/protocol/Exchange/MixinMatchOrders.sol2
-rw-r--r--contracts/core/contracts/protocol/Exchange/MixinSignatureValidator.sol16
-rw-r--r--contracts/core/contracts/protocol/Exchange/MixinWrapperFunctions.sol2
-rw-r--r--contracts/core/contracts/protocol/Exchange/libs/LibFillResults.sol2
-rw-r--r--contracts/core/contracts/protocol/Exchange/libs/LibMath.sol2
-rw-r--r--contracts/core/contracts/test/DummyERC20Token/DummyERC20Token.sol2
-rw-r--r--contracts/core/contracts/test/DummyERC721Token/DummyERC721Token.sol2
-rw-r--r--contracts/core/contracts/test/ReentrantERC20Token/ReentrantERC20Token.sol2
-rw-r--r--contracts/core/contracts/tokens/ERC20Token/MintableERC20Token.sol2
-rw-r--r--contracts/core/contracts/tokens/ERC721Token/ERC721Token.sol2
-rw-r--r--contracts/core/package.json14
-rw-r--r--contracts/core/src/artifacts/index.ts10
-rw-r--r--contracts/core/src/wrappers/index.ts5
-rw-r--r--contracts/core/test/asset_proxy/authorizable.ts12
-rw-r--r--contracts/core/test/asset_proxy/proxies.ts17
-rw-r--r--contracts/core/test/exchange/core.ts20
-rw-r--r--contracts/core/test/exchange/dispatcher.ts16
-rw-r--r--contracts/core/test/exchange/fill_order.ts22
-rw-r--r--contracts/core/test/exchange/internal.ts18
-rw-r--r--contracts/core/test/exchange/libs.ts30
-rw-r--r--contracts/core/test/exchange/match_orders.ts17
-rw-r--r--contracts/core/test/exchange/signature_validator.ts20
-rw-r--r--contracts/core/test/exchange/transactions.ts21
-rw-r--r--contracts/core/test/exchange/wrapper.ts20
-rw-r--r--contracts/core/test/extensions/dutch_auction.ts491
-rw-r--r--contracts/core/test/extensions/forwarder.ts23
-rw-r--r--contracts/core/test/extensions/order_validator.ts14
-rw-r--r--contracts/core/test/global_hooks.ts8
-rw-r--r--contracts/core/test/multisig/asset_proxy_owner.ts102
-rw-r--r--contracts/core/test/tokens/erc721_token.ts17
-rw-r--r--contracts/core/test/tokens/unlimited_allowance_token.ts12
-rw-r--r--contracts/core/test/tokens/weth9.ts13
-rw-r--r--contracts/core/test/tokens/zrx_token.ts4
-rw-r--r--contracts/core/test/utils/asset_proxy_owner_wrapper.ts69
-rw-r--r--contracts/core/test/utils/asset_wrapper.ts3
-rw-r--r--contracts/core/test/utils/erc20_wrapper.ts5
-rw-r--r--contracts/core/test/utils/erc721_wrapper.ts5
-rw-r--r--contracts/core/test/utils/exchange_wrapper.ts16
-rw-r--r--contracts/core/test/utils/fill_order_combinatorial_utils.ts34
-rw-r--r--contracts/core/test/utils/forwarder_wrapper.ts9
-rw-r--r--contracts/core/test/utils/match_order_tester.ts26
-rw-r--r--contracts/core/test/utils/order_factory_from_scenario.ts15
-rw-r--r--contracts/core/tsconfig.json5
-rw-r--r--contracts/multisig/.solhint.json20
-rw-r--r--contracts/multisig/CHANGELOG.json1
-rw-r--r--contracts/multisig/README.md70
-rw-r--r--contracts/multisig/compiler.json22
-rw-r--r--contracts/multisig/contracts/multisig/MultiSigWallet.sol (renamed from contracts/core/contracts/multisig/MultiSigWallet.sol)0
-rw-r--r--contracts/multisig/contracts/multisig/MultiSigWalletWithTimeLock.sol (renamed from contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol)0
-rw-r--r--contracts/multisig/contracts/test/TestRejectEther/TestRejectEther.sol23
-rw-r--r--contracts/multisig/package.json86
-rw-r--r--contracts/multisig/src/artifacts/index.ts11
-rw-r--r--contracts/multisig/src/wrappers/index.ts2
-rw-r--r--contracts/multisig/test/global_hooks.ts19
-rw-r--r--contracts/multisig/test/multi_sig_with_time_lock.ts (renamed from contracts/core/test/multisig/multi_sig_with_time_lock.ts)32
-rw-r--r--contracts/multisig/test/utils/multi_sig_wrapper.ts (renamed from contracts/core/test/utils/multi_sig_wrapper.ts)19
-rw-r--r--contracts/multisig/tsconfig.json15
-rw-r--r--contracts/multisig/tslint.json6
-rw-r--r--contracts/test-utils/README.md73
-rw-r--r--contracts/test-utils/package.json75
-rw-r--r--contracts/test-utils/src/abstract_asset_wrapper.ts (renamed from contracts/core/test/utils/abstract_asset_wrapper.ts)0
-rw-r--r--contracts/test-utils/src/address_utils.ts (renamed from contracts/core/test/utils/address_utils.ts)0
-rw-r--r--contracts/test-utils/src/assertions.ts (renamed from contracts/core/test/utils/assertions.ts)0
-rw-r--r--contracts/test-utils/src/block_timestamp.ts (renamed from contracts/core/test/utils/block_timestamp.ts)0
-rw-r--r--contracts/test-utils/src/chai_setup.ts (renamed from contracts/core/test/utils/chai_setup.ts)0
-rw-r--r--contracts/test-utils/src/combinatorial_utils.ts (renamed from contracts/core/test/utils/combinatorial_utils.ts)0
-rw-r--r--contracts/test-utils/src/constants.ts (renamed from contracts/core/test/utils/constants.ts)0
-rw-r--r--contracts/test-utils/src/coverage.ts (renamed from contracts/core/test/utils/coverage.ts)0
-rw-r--r--contracts/test-utils/src/formatters.ts (renamed from contracts/core/test/utils/formatters.ts)0
-rw-r--r--contracts/test-utils/src/global_hooks.ts15
-rw-r--r--contracts/test-utils/src/index.ts55
-rw-r--r--contracts/test-utils/src/log_decoder.ts (renamed from contracts/core/test/utils/log_decoder.ts)4
-rw-r--r--contracts/test-utils/src/order_factory.ts (renamed from contracts/core/test/utils/order_factory.ts)0
-rw-r--r--contracts/test-utils/src/order_utils.ts (renamed from contracts/core/test/utils/order_utils.ts)0
-rw-r--r--contracts/test-utils/src/profiler.ts (renamed from contracts/core/test/utils/profiler.ts)0
-rw-r--r--contracts/test-utils/src/revert_trace.ts (renamed from contracts/core/test/utils/revert_trace.ts)0
-rw-r--r--contracts/test-utils/src/signing_utils.ts (renamed from contracts/core/test/utils/signing_utils.ts)0
-rw-r--r--contracts/test-utils/src/test_with_reference.ts (renamed from contracts/core/test/utils/test_with_reference.ts)0
-rw-r--r--contracts/test-utils/src/transaction_factory.ts (renamed from contracts/core/test/utils/transaction_factory.ts)0
-rw-r--r--contracts/test-utils/src/type_encoding_utils.ts (renamed from contracts/core/test/utils/type_encoding_utils.ts)0
-rw-r--r--contracts/test-utils/src/types.ts (renamed from contracts/core/test/utils/types.ts)1
-rw-r--r--contracts/test-utils/src/web3_wrapper.ts (renamed from contracts/core/test/utils/web3_wrapper.ts)1
-rw-r--r--contracts/test-utils/test/test_with_reference.ts (renamed from contracts/core/test/utils_test/test_with_reference.ts)4
-rw-r--r--contracts/test-utils/tsconfig.json7
-rw-r--r--contracts/test-utils/tsconfig.lint.json7
-rw-r--r--contracts/test-utils/tslint.json6
-rw-r--r--contracts/utils/.solhint.json20
-rw-r--r--contracts/utils/README.md70
-rw-r--r--contracts/utils/compiler.json22
-rw-r--r--contracts/utils/contracts/test/TestConstants/TestConstants.sol (renamed from contracts/core/contracts/test/TestConstants/TestConstants.sol)2
-rw-r--r--contracts/utils/contracts/test/TestLibBytes/TestLibBytes.sol (renamed from contracts/core/contracts/test/TestLibBytes/TestLibBytes.sol)2
-rw-r--r--contracts/utils/contracts/utils/LibBytes/LibBytes.sol (renamed from contracts/core/contracts/utils/LibBytes/LibBytes.sol)0
-rw-r--r--contracts/utils/contracts/utils/Ownable/IOwnable.sol (renamed from contracts/core/contracts/utils/Ownable/IOwnable.sol)0
-rw-r--r--contracts/utils/contracts/utils/Ownable/Ownable.sol (renamed from contracts/core/contracts/utils/Ownable/Ownable.sol)0
-rw-r--r--contracts/utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol (renamed from contracts/core/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol)0
-rw-r--r--contracts/utils/contracts/utils/SafeMath/SafeMath.sol (renamed from contracts/core/contracts/utils/SafeMath/SafeMath.sol)0
-rw-r--r--contracts/utils/package.json90
-rw-r--r--contracts/utils/src/artifacts/index.ts19
-rw-r--r--contracts/utils/src/index.ts2
-rw-r--r--contracts/utils/src/wrappers/index.ts2
-rw-r--r--contracts/utils/test/global_hooks.ts17
-rw-r--r--contracts/utils/test/lib_bytes.ts (renamed from contracts/core/test/libraries/lib_bytes.ts)18
-rw-r--r--contracts/utils/test/libs.ts34
-rw-r--r--contracts/utils/tsconfig.json19
-rw-r--r--contracts/utils/tslint.json6
-rw-r--r--packages/0x.js/.npmignore2
-rw-r--r--packages/abi-gen/README.md4
-rw-r--r--packages/asset-buyer/CHANGELOG.json8
-rw-r--r--packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts8
-rw-r--r--packages/contract-wrappers/.npmignore2
-rw-r--r--packages/instant/.dogfood.discharge.json2
-rw-r--r--packages/instant/.env_example5
-rw-r--r--packages/instant/.production.discharge.json2
-rw-r--r--packages/instant/.staging.discharge.json2
-rw-r--r--packages/instant/src/components/buy_order_progress.tsx2
-rw-r--r--packages/instant/src/components/erc20_asset_amount_input.tsx8
-rw-r--r--packages/instant/src/components/instant_heading.tsx2
-rw-r--r--packages/instant/src/components/order_details.tsx2
-rw-r--r--packages/instant/src/components/payment_method.tsx2
-rw-r--r--packages/instant/src/constants.ts1
-rw-r--r--packages/instant/src/data/asset_meta_data_map.ts2
-rw-r--r--packages/instant/src/redux/async_data.ts3
-rw-r--r--packages/instant/src/util/analytics.ts12
-rw-r--r--packages/instant/webpack.config.js2
-rw-r--r--packages/monorepo-scripts/CHANGELOG.json4
-rw-r--r--packages/monorepo-scripts/src/utils/github_release_utils.ts12
-rw-r--r--packages/sol-compiler/CHANGELOG.json9
-rw-r--r--packages/sol-compiler/src/compiler.ts9
-rw-r--r--packages/sol-resolver/CHANGELOG.json9
-rw-r--r--packages/sol-resolver/src/resolvers/npm_resolver.ts15
-rw-r--r--packages/types/CHANGELOG.json4
-rw-r--r--packages/types/src/index.ts6
151 files changed, 2114 insertions, 425 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 0ab512f58..fe81054ac 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -40,7 +40,9 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- - run: yarn wsrun test:circleci contracts
+ - run: yarn wsrun test:circleci @0x/contracts-multisig
+ - run: yarn wsrun test:circleci @0x/contracts-utils
+ - run: yarn wsrun test:circleci @0x/contracts-core
test-contracts-geth:
docker:
- image: circleci/node:9
@@ -52,7 +54,9 @@ jobs:
- repo-{{ .Environment.CIRCLE_SHA1 }}
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
# initialized
- - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
+ - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test @0x/contracts-multisig
+ - run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-utils
+ - run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-core
test-publish:
resource_class: medium+
docker:
@@ -81,6 +85,7 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
+ - run: yarn wsrun test:circleci @0x/contracts-test-utils
- run: yarn wsrun test:circleci @0x/abi-gen
- run: yarn wsrun test:circleci @0x/assert
- run: yarn wsrun test:circleci @0x/base-contract
diff --git a/.gitignore b/.gitignore
index 0e483dc0a..6a82f3e26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,12 +80,16 @@ packages/testnet-faucets/server/
# generated contract artifacts/
contracts/core/generated-artifacts/
+contracts/multisig/generated-artifacts/
+contracts/utils/generated-artifacts/
packages/sol-cov/test/fixtures/artifacts/
packages/metacoin/artifacts/
# generated contract wrappers
packages/abi-gen-wrappers/wrappers
contracts/core/generated-wrappers/
+contracts/multisig/generated-wrappers/
+contracts/utils/generated-wrappers/
packages/metacoin/src/contract_wrappers
# solc-bin in sol-compiler
diff --git a/.prettierignore b/.prettierignore
index 9dbb83e27..9684a83b7 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,6 +2,10 @@ lib
.nyc_output
/contracts/core/generated-wrappers
/contracts/core/generated-artifacts
+/contracts/multisig/generated-wrappers
+/contracts/multisig/generated-artifacts
+/contracts/utils/generated-wrappers
+/contracts/utils/generated-artifacts
/packages/abi-gen-wrappers/src/generated-wrappers
/packages/contract-artifacts/artifacts
/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
diff --git a/CODEOWNERS b/CODEOWNERS
index 346e42ac0..ca98ec19b 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -14,7 +14,7 @@ packages/website/ @BMillman19 @fragosti @fabioberger @steveklebanoff
packages/abi-gen/ @LogvinovLeon
packages/base-contract/ @LogvinovLeon
packages/connect/ @fragosti
-packages/contract_templates/ @LogvinovLeon
+packages/abi-gen-templates/ @LogvinovLeon
packages/contract-addresses/ @albrow
packages/contract-artifacts/ @albrow
packages/dev-utils/ @LogvinovLeon @fabioberger
diff --git a/contracts/TESTING.md b/contracts/TESTING.md
new file mode 100644
index 000000000..750b3c62c
--- /dev/null
+++ b/contracts/TESTING.md
@@ -0,0 +1,48 @@
+# Contracts testing options
+
+## Revert stack traces
+
+If you want to see helpful stack traces (incl. line number, code snippet) for smart contract reverts, run the tests with:
+
+```
+yarn test:trace
+```
+
+**Note:** This currently slows down the test runs and is therefore not enabled by default.
+
+## Backing Ethereum node
+
+By default, our tests run against an in-process [Ganache](https://github.com/trufflesuite/ganache-core) instance. In order to run the tests against [Geth](https://github.com/ethereum/go-ethereum), first follow the instructions in the README for the devnet package to start the devnet Geth node. Then run:
+
+```bash
+TEST_PROVIDER=geth yarn test
+```
+
+## Code coverage
+
+In order to see the Solidity code coverage output generated by `@0x/sol-cov`, run:
+
+```
+yarn test:coverage
+```
+
+## Gas profiler
+
+In order to profile the gas costs for a specific smart contract call/transaction, you can run the tests in `profiler` mode.
+
+**Note:** Traces emitted by ganache have incorrect gas costs so we recommend using Geth for profiling.
+
+```
+TEST_PROVIDER=geth yarn test:profiler
+```
+
+You'll see a warning that you need to explicitly enable and disable the profiler before and after the block of code you want to profile.
+
+```typescript
+import { profiler } from './utils/profiler';
+profiler.start();
+// Some call to a smart contract
+profiler.stop();
+```
+
+Without explicitly starting and stopping the profiler, the profiler output will be too busy, and therefore unusable.
diff --git a/contracts/core/README.md b/contracts/core/README.md
index 97a2816ff..0004925c1 100644
--- a/contracts/core/README.md
+++ b/contracts/core/README.md
@@ -14,8 +14,6 @@ Contracts that make up and interact with version 2.0.0 of the protocol can be fo
* This directory contains example implementations of contracts that interact with the protocol but are _not_ intended for use in production. Examples include [filter](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#filter-contracts) contracts, a [Wallet](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#wallet) contract, and a [Validator](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#validator) contract, among others.
* [tokens](./contracts/tokens)
* This directory contains implementations of different tokens and token standards, including [wETH](https://weth.io/), ZRX, [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md), and [ERC721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md).
-* [multisig](./contracts/multisig)
- * This directory contains the [Gnosis MultiSigWallet](https://github.com/gnosis/MultiSigWallet) and a custom extension that adds a timelock to transactions within the MultiSigWallet.
* [utils](./contracts/utils)
* This directory contains libraries and utils that are shared across all of the other directories.
* [test](./contracts/test)
@@ -52,13 +50,13 @@ yarn install
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
-PKG=contracts yarn build
+PKG=@0x/contracts-core yarn build
```
Or continuously rebuild on change:
```bash
-PKG=contracts yarn watch
+PKG=@0x/contracts-core yarn watch
```
### Clean
@@ -81,49 +79,4 @@ yarn test
#### Testing options
-###### Revert stack traces
-
-If you want to see helpful stack traces (incl. line number, code snippet) for smart contract reverts, run the tests with:
-
-```
-yarn test:trace
-```
-
-**Note:** This currently slows down the test runs and is therefore not enabled by default.
-
-###### Backing Ethereum node
-
-By default, our tests run against an in-process [Ganache](https://github.com/trufflesuite/ganache-core) instance. In order to run the tests against [Geth](https://github.com/ethereum/go-ethereum), first follow the instructions in the README for the devnet package to start the devnet Geth node. Then run:
-
-```bash
-TEST_PROVIDER=geth yarn test
-```
-
-###### Code coverage
-
-In order to see the Solidity code coverage output generated by `@0x/sol-cov`, run:
-
-```
-yarn test:coverage
-```
-
-###### Gas profiler
-
-In order to profile the gas costs for a specific smart contract call/transaction, you can run the tests in `profiler` mode.
-
-**Note:** Traces emitted by ganache have incorrect gas costs so we recommend using Geth for profiling.
-
-```
-TEST_PROVIDER=geth yarn test:profiler
-```
-
-You'll see a warning that you need to explicitly enable and disable the profiler before and after the block of code you want to profile.
-
-```typescript
-import { profiler } from './utils/profiler';
-profiler.start();
-// Some call to a smart contract
-profiler.stop();
-```
-
-Without explicitly starting and stopping the profiler, the profiler output will be too busy, and therefore unusable.
+Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
diff --git a/contracts/core/compiler.json b/contracts/core/compiler.json
index c824e4645..8d9732794 100644
--- a/contracts/core/compiler.json
+++ b/contracts/core/compiler.json
@@ -25,6 +25,7 @@
"DummyERC721Token",
"DummyMultipleReturnERC20Token",
"DummyNoReturnERC20Token",
+ "DutchAuction",
"ERC20Proxy",
"ERC20Token",
"ERC721Token",
@@ -39,14 +40,10 @@
"IWallet",
"MixinAuthorizable",
"MultiAssetProxy",
- "MultiSigWallet",
- "MultiSigWalletWithTimeLock",
"OrderValidator",
"ReentrantERC20Token",
"TestAssetProxyOwner",
"TestAssetProxyDispatcher",
- "TestConstants",
- "TestLibBytes",
"TestLibs",
"TestExchangeInternals",
"TestSignatureValidator",
diff --git a/contracts/core/contracts/examples/Wallet/Wallet.sol b/contracts/core/contracts/examples/Wallet/Wallet.sol
index b75021a31..3738be841 100644
--- a/contracts/core/contracts/examples/Wallet/Wallet.sol
+++ b/contracts/core/contracts/examples/Wallet/Wallet.sol
@@ -19,7 +19,7 @@
pragma solidity 0.4.24;
import "../../protocol/Exchange/interfaces/IWallet.sol";
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
contract Wallet is
diff --git a/contracts/core/contracts/examples/Whitelist/Whitelist.sol b/contracts/core/contracts/examples/Whitelist/Whitelist.sol
index e4e25038c..61c21c095 100644
--- a/contracts/core/contracts/examples/Whitelist/Whitelist.sol
+++ b/contracts/core/contracts/examples/Whitelist/Whitelist.sol
@@ -21,7 +21,7 @@ pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
contract Whitelist is
diff --git a/contracts/core/contracts/extensions/DutchAuction/DutchAuction.sol b/contracts/core/contracts/extensions/DutchAuction/DutchAuction.sol
new file mode 100644
index 000000000..dfd4c46dc
--- /dev/null
+++ b/contracts/core/contracts/extensions/DutchAuction/DutchAuction.sol
@@ -0,0 +1,205 @@
+/*
+
+ Copyright 2018 ZeroEx Intl.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+pragma solidity 0.4.24;
+pragma experimental ABIEncoderV2;
+
+import "../../protocol/Exchange/interfaces/IExchange.sol";
+import "../../protocol/Exchange/libs/LibOrder.sol";
+import "../../tokens/ERC20Token/IERC20Token.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
+
+
+contract DutchAuction is
+ SafeMath
+{
+ using LibBytes for bytes;
+
+ // solhint-disable var-name-mixedcase
+ IExchange internal EXCHANGE;
+
+ struct AuctionDetails {
+ uint256 beginTimeSeconds; // Auction begin unix timestamp: sellOrder.makerAssetData
+ uint256 endTimeSeconds; // Auction end unix timestamp: sellOrder.expiryTimeSeconds
+ uint256 beginAmount; // Auction begin amount: sellOrder.makerAssetData
+ uint256 endAmount; // Auction end amount: sellOrder.takerAssetAmount
+ uint256 currentAmount; // Calculated amount given block.timestamp
+ uint256 currentTimeSeconds; // block.timestamp
+ }
+
+ constructor (address _exchange)
+ public
+ {
+ EXCHANGE = IExchange(_exchange);
+ }
+
+ /// @dev Matches the buy and sell orders at an amount given the following: the current block time, the auction
+ /// start time and the auction begin amount. The sell order is a an order at the lowest amount
+ /// at the end of the auction. Excess from the match is transferred to the seller.
+ /// Over time the price moves from beginAmount to endAmount given the current block.timestamp.
+ /// sellOrder.expiryTimeSeconds is the end time of the auction.
+ /// sellOrder.takerAssetAmount is the end amount of the auction (lowest possible amount).
+ /// sellOrder.makerAssetData is the ABI encoded Asset Proxy data with the following data appended
+ /// buyOrder.makerAssetData is the buyers bid on the auction, must meet the amount for the current block timestamp
+ /// (uint256 beginTimeSeconds, uint256 beginAmount).
+ /// This function reverts in the following scenarios:
+ /// * Auction has not started (auctionDetails.currentTimeSeconds < auctionDetails.beginTimeSeconds)
+ /// * Auction has expired (auctionDetails.endTimeSeconds < auctionDetails.currentTimeSeconds)
+ /// * Amount is invalid: Buy order amount is too low (buyOrder.makerAssetAmount < auctionDetails.currentAmount)
+ /// * Amount is invalid: Invalid begin amount (auctionDetails.beginAmount > auctionDetails.endAmount)
+ /// * Any failure in the 0x Match Orders
+ /// @param buyOrder The Buyer's order. This order is for the current expected price of the auction.
+ /// @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
+ /// @param buySignature Proof that order was created by the buyer.
+ /// @param sellSignature Proof that order was created by the seller.
+ /// @return matchedFillResults amounts filled and fees paid by maker and taker of matched orders.
+ function matchOrders(
+ LibOrder.Order memory buyOrder,
+ LibOrder.Order memory sellOrder,
+ bytes memory buySignature,
+ bytes memory sellSignature
+ )
+ public
+ returns (LibFillResults.MatchedFillResults memory matchedFillResults)
+ {
+ AuctionDetails memory auctionDetails = getAuctionDetails(sellOrder);
+ // Ensure the auction has not yet started
+ require(
+ auctionDetails.currentTimeSeconds >= auctionDetails.beginTimeSeconds,
+ "AUCTION_NOT_STARTED"
+ );
+ // Ensure the auction has not expired. This will fail later in 0x but we can save gas by failing early
+ require(
+ sellOrder.expirationTimeSeconds > auctionDetails.currentTimeSeconds,
+ "AUCTION_EXPIRED"
+ );
+ // Validate the buyer amount is greater than the current auction amount
+ require(
+ buyOrder.makerAssetAmount >= auctionDetails.currentAmount,
+ "INVALID_AMOUNT"
+ );
+ // Match orders, maximally filling `buyOrder`
+ matchedFillResults = EXCHANGE.matchOrders(
+ buyOrder,
+ sellOrder,
+ buySignature,
+ sellSignature
+ );
+ // The difference in sellOrder.takerAssetAmount and current amount is given as spread to the matcher
+ // This may include additional spread from the buyOrder.makerAssetAmount and the currentAmount.
+ // e.g currentAmount is 30, sellOrder.takerAssetAmount is 10 and buyOrder.makerAssetamount is 40.
+ // 10 (40-30) is returned to the buyer, 20 (30-10) sent to the seller and 10 has previously
+ // been transferred to the seller during matchOrders
+ uint256 leftMakerAssetSpreadAmount = matchedFillResults.leftMakerAssetSpreadAmount;
+ if (leftMakerAssetSpreadAmount > 0) {
+ // ERC20 Asset data itself is encoded as follows:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 1 * 32 | function parameters: |
+ // | | 4 | 12 | 1. token address padding |
+ // | | 16 | 20 | 2. token address |
+ bytes memory assetData = sellOrder.takerAssetData;
+ address token = assetData.readAddress(16);
+ // Calculate the excess from the buy order. This can occur if the buyer sends in a higher
+ // amount than the calculated current amount
+ uint256 buyerExcessAmount = safeSub(buyOrder.makerAssetAmount, auctionDetails.currentAmount);
+ uint256 sellerExcessAmount = safeSub(leftMakerAssetSpreadAmount, buyerExcessAmount);
+ // Return the difference between auctionDetails.currentAmount and sellOrder.takerAssetAmount
+ // to the seller
+ if (sellerExcessAmount > 0) {
+ IERC20Token(token).transfer(sellOrder.makerAddress, sellerExcessAmount);
+ }
+ // Return the difference between buyOrder.makerAssetAmount and auctionDetails.currentAmount
+ // to the buyer
+ if (buyerExcessAmount > 0) {
+ IERC20Token(token).transfer(buyOrder.makerAddress, buyerExcessAmount);
+ }
+ }
+ return matchedFillResults;
+ }
+
+ /// @dev Calculates the Auction Details for the given order
+ /// @param order The sell order
+ /// @return AuctionDetails
+ function getAuctionDetails(
+ LibOrder.Order memory order
+ )
+ public
+ returns (AuctionDetails memory auctionDetails)
+ {
+ uint256 makerAssetDataLength = order.makerAssetData.length;
+ // It is unknown the encoded data of makerAssetData, we assume the last 64 bytes
+ // are the Auction Details encoding.
+ // Auction Details is encoded as follows:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Params | | 2 * 32 | parameters: |
+ // | | -64 | 32 | 1. auction begin unix timestamp |
+ // | | -32 | 32 | 2. auction begin begin amount |
+ // ERC20 asset data length is 4+32, 64 for auction details results in min length 100
+ require(
+ makerAssetDataLength >= 100,
+ "INVALID_ASSET_DATA"
+ );
+ uint256 auctionBeginTimeSeconds = order.makerAssetData.readUint256(makerAssetDataLength - 64);
+ uint256 auctionBeginAmount = order.makerAssetData.readUint256(makerAssetDataLength - 32);
+ // Ensure the auction has a valid begin time
+ require(
+ order.expirationTimeSeconds > auctionBeginTimeSeconds,
+ "INVALID_BEGIN_TIME"
+ );
+ uint256 auctionDurationSeconds = order.expirationTimeSeconds-auctionBeginTimeSeconds;
+ // Ensure the auction goes from high to low
+ uint256 minAmount = order.takerAssetAmount;
+ require(
+ auctionBeginAmount > minAmount,
+ "INVALID_AMOUNT"
+ );
+ uint256 amountDelta = auctionBeginAmount-minAmount;
+ // solhint-disable-next-line not-rely-on-time
+ uint256 timestamp = block.timestamp;
+ auctionDetails.beginTimeSeconds = auctionBeginTimeSeconds;
+ auctionDetails.endTimeSeconds = order.expirationTimeSeconds;
+ auctionDetails.beginAmount = auctionBeginAmount;
+ auctionDetails.endAmount = minAmount;
+ auctionDetails.currentTimeSeconds = timestamp;
+
+ uint256 remainingDurationSeconds = order.expirationTimeSeconds-timestamp;
+ if (timestamp < auctionBeginTimeSeconds) {
+ // If the auction has not yet begun the current amount is the auctionBeginAmount
+ auctionDetails.currentAmount = auctionBeginAmount;
+ } else if (timestamp >= order.expirationTimeSeconds) {
+ // If the auction has ended the current amount is the minAmount.
+ // Auction end time is guaranteed by 0x Exchange due to the order expiration
+ auctionDetails.currentAmount = minAmount;
+ } else {
+ auctionDetails.currentAmount = safeAdd(
+ minAmount,
+ safeDiv(
+ safeMul(remainingDurationSeconds, amountDelta),
+ auctionDurationSeconds
+ )
+ );
+ }
+ return auctionDetails;
+ }
+}
diff --git a/contracts/core/contracts/extensions/Forwarder/MixinAssets.sol b/contracts/core/contracts/extensions/Forwarder/MixinAssets.sol
index 43efb5ff3..5f5f3456d 100644
--- a/contracts/core/contracts/extensions/Forwarder/MixinAssets.sol
+++ b/contracts/core/contracts/extensions/Forwarder/MixinAssets.sol
@@ -18,8 +18,8 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
import "../../tokens/ERC20Token/IERC20Token.sol";
import "../../tokens/ERC721Token/IERC721Token.sol";
import "./libs/LibConstants.sol";
diff --git a/contracts/core/contracts/extensions/Forwarder/MixinForwarderCore.sol b/contracts/core/contracts/extensions/Forwarder/MixinForwarderCore.sol
index 54487f726..a5dd99225 100644
--- a/contracts/core/contracts/extensions/Forwarder/MixinForwarderCore.sol
+++ b/contracts/core/contracts/extensions/Forwarder/MixinForwarderCore.sol
@@ -24,7 +24,7 @@ import "./mixins/MWeth.sol";
import "./mixins/MAssets.sol";
import "./mixins/MExchangeWrapper.sol";
import "./interfaces/IForwarderCore.sol";
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
import "../../protocol/Exchange/libs/LibFillResults.sol";
import "../../protocol/Exchange/libs/LibMath.sol";
diff --git a/contracts/core/contracts/extensions/Forwarder/libs/LibConstants.sol b/contracts/core/contracts/extensions/Forwarder/libs/LibConstants.sol
index 704e42ce3..0f98ae595 100644
--- a/contracts/core/contracts/extensions/Forwarder/libs/LibConstants.sol
+++ b/contracts/core/contracts/extensions/Forwarder/libs/LibConstants.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
import "../../../protocol/Exchange/interfaces/IExchange.sol";
import "../../../tokens/EtherToken/IEtherToken.sol";
import "../../../tokens/ERC20Token/IERC20Token.sol";
diff --git a/contracts/core/contracts/extensions/OrderValidator/OrderValidator.sol b/contracts/core/contracts/extensions/OrderValidator/OrderValidator.sol
index 3385d35ef..e3f4f6832 100644
--- a/contracts/core/contracts/extensions/OrderValidator/OrderValidator.sol
+++ b/contracts/core/contracts/extensions/OrderValidator/OrderValidator.sol
@@ -23,7 +23,7 @@ import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
import "../../tokens/ERC20Token/IERC20Token.sol";
import "../../tokens/ERC721Token/IERC721Token.sol";
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
contract OrderValidator {
diff --git a/contracts/core/contracts/protocol/AssetProxy/MixinAuthorizable.sol b/contracts/core/contracts/protocol/AssetProxy/MixinAuthorizable.sol
index fe9bbf848..08f9b94dc 100644
--- a/contracts/core/contracts/protocol/AssetProxy/MixinAuthorizable.sol
+++ b/contracts/core/contracts/protocol/AssetProxy/MixinAuthorizable.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
import "./mixins/MAuthorizable.sol";
diff --git a/contracts/core/contracts/protocol/AssetProxy/interfaces/IAuthorizable.sol b/contracts/core/contracts/protocol/AssetProxy/interfaces/IAuthorizable.sol
index ba1d4aa77..96ee05dee 100644
--- a/contracts/core/contracts/protocol/AssetProxy/interfaces/IAuthorizable.sol
+++ b/contracts/core/contracts/protocol/AssetProxy/interfaces/IAuthorizable.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../../utils/Ownable/IOwnable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/IOwnable.sol";
contract IAuthorizable is
diff --git a/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol b/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol
index edb788fab..bfc7b5a66 100644
--- a/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol
+++ b/contracts/core/contracts/protocol/AssetProxyOwner/AssetProxyOwner.sol
@@ -18,8 +18,8 @@
pragma solidity 0.4.24;
-import "../../multisig/MultiSigWalletWithTimeLock.sol";
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-multisig/contracts/multisig/MultiSigWalletWithTimeLock.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
contract AssetProxyOwner is
diff --git a/contracts/core/contracts/protocol/Exchange/MixinAssetProxyDispatcher.sol b/contracts/core/contracts/protocol/Exchange/MixinAssetProxyDispatcher.sol
index 87b09b6b3..02aeb4a13 100644
--- a/contracts/core/contracts/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/contracts/core/contracts/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
import "./mixins/MAssetProxyDispatcher.sol";
import "../AssetProxy/interfaces/IAssetProxy.sol";
diff --git a/contracts/core/contracts/protocol/Exchange/MixinExchangeCore.sol b/contracts/core/contracts/protocol/Exchange/MixinExchangeCore.sol
index 736dcd0b1..da721f78f 100644
--- a/contracts/core/contracts/protocol/Exchange/MixinExchangeCore.sol
+++ b/contracts/core/contracts/protocol/Exchange/MixinExchangeCore.sol
@@ -19,7 +19,7 @@
pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
-import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
+import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
import "./libs/LibConstants.sol";
import "./libs/LibFillResults.sol";
import "./libs/LibOrder.sol";
diff --git a/contracts/core/contracts/protocol/Exchange/MixinMatchOrders.sol b/contracts/core/contracts/protocol/Exchange/MixinMatchOrders.sol
index b4f6bdb26..da1e9d270 100644
--- a/contracts/core/contracts/protocol/Exchange/MixinMatchOrders.sol
+++ b/contracts/core/contracts/protocol/Exchange/MixinMatchOrders.sol
@@ -14,7 +14,7 @@
pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
-import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
+import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
import "./libs/LibConstants.sol";
import "./libs/LibMath.sol";
import "./libs/LibOrder.sol";
diff --git a/contracts/core/contracts/protocol/Exchange/MixinSignatureValidator.sol b/contracts/core/contracts/protocol/Exchange/MixinSignatureValidator.sol
index 176e28351..711535aa8 100644
--- a/contracts/core/contracts/protocol/Exchange/MixinSignatureValidator.sol
+++ b/contracts/core/contracts/protocol/Exchange/MixinSignatureValidator.sol
@@ -18,8 +18,8 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
-import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
import "./interfaces/IWallet.sol";
@@ -239,18 +239,18 @@ contract MixinSignatureValidator is
view
returns (bool isValid)
{
- bytes memory calldata = abi.encodeWithSelector(
+ bytes memory callData = abi.encodeWithSelector(
IWallet(walletAddress).isValidSignature.selector,
hash,
signature
);
assembly {
- let cdStart := add(calldata, 32)
+ let cdStart := add(callData, 32)
let success := staticcall(
gas, // forward all gas
walletAddress, // address of Wallet contract
cdStart, // pointer to start of input
- mload(calldata), // length of input
+ mload(callData), // length of input
cdStart, // write output over input
32 // output size is 32 bytes
)
@@ -288,19 +288,19 @@ contract MixinSignatureValidator is
view
returns (bool isValid)
{
- bytes memory calldata = abi.encodeWithSelector(
+ bytes memory callData = abi.encodeWithSelector(
IValidator(signerAddress).isValidSignature.selector,
hash,
signerAddress,
signature
);
assembly {
- let cdStart := add(calldata, 32)
+ let cdStart := add(callData, 32)
let success := staticcall(
gas, // forward all gas
validatorAddress, // address of Validator contract
cdStart, // pointer to start of input
- mload(calldata), // length of input
+ mload(callData), // length of input
cdStart, // write output over input
32 // output size is 32 bytes
)
diff --git a/contracts/core/contracts/protocol/Exchange/MixinWrapperFunctions.sol b/contracts/core/contracts/protocol/Exchange/MixinWrapperFunctions.sol
index cddff0e5f..415246358 100644
--- a/contracts/core/contracts/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/contracts/core/contracts/protocol/Exchange/MixinWrapperFunctions.sol
@@ -19,7 +19,7 @@
pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
-import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
+import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
import "./libs/LibMath.sol";
import "./libs/LibOrder.sol";
import "./libs/LibFillResults.sol";
diff --git a/contracts/core/contracts/protocol/Exchange/libs/LibFillResults.sol b/contracts/core/contracts/protocol/Exchange/libs/LibFillResults.sol
index 659ae9a69..fbd9950bf 100644
--- a/contracts/core/contracts/protocol/Exchange/libs/LibFillResults.sol
+++ b/contracts/core/contracts/protocol/Exchange/libs/LibFillResults.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../../utils/SafeMath/SafeMath.sol";
+import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
contract LibFillResults is
diff --git a/contracts/core/contracts/protocol/Exchange/libs/LibMath.sol b/contracts/core/contracts/protocol/Exchange/libs/LibMath.sol
index c0b85ea10..b24876a9c 100644
--- a/contracts/core/contracts/protocol/Exchange/libs/LibMath.sol
+++ b/contracts/core/contracts/protocol/Exchange/libs/LibMath.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../../utils/SafeMath/SafeMath.sol";
+import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
contract LibMath is
diff --git a/contracts/core/contracts/test/DummyERC20Token/DummyERC20Token.sol b/contracts/core/contracts/test/DummyERC20Token/DummyERC20Token.sol
index 412c5d1ad..33028db0c 100644
--- a/contracts/core/contracts/test/DummyERC20Token/DummyERC20Token.sol
+++ b/contracts/core/contracts/test/DummyERC20Token/DummyERC20Token.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
import "../../tokens/ERC20Token/MintableERC20Token.sol";
diff --git a/contracts/core/contracts/test/DummyERC721Token/DummyERC721Token.sol b/contracts/core/contracts/test/DummyERC721Token/DummyERC721Token.sol
index ac9068d1d..4c978b2df 100644
--- a/contracts/core/contracts/test/DummyERC721Token/DummyERC721Token.sol
+++ b/contracts/core/contracts/test/DummyERC721Token/DummyERC721Token.sol
@@ -19,7 +19,7 @@
pragma solidity 0.4.24;
import "../../tokens/ERC721Token/MintableERC721Token.sol";
-import "../../utils/Ownable/Ownable.sol";
+import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
// solhint-disable no-empty-blocks
diff --git a/contracts/core/contracts/test/ReentrantERC20Token/ReentrantERC20Token.sol b/contracts/core/contracts/test/ReentrantERC20Token/ReentrantERC20Token.sol
index aa3bf9ab8..3e9091931 100644
--- a/contracts/core/contracts/test/ReentrantERC20Token/ReentrantERC20Token.sol
+++ b/contracts/core/contracts/test/ReentrantERC20Token/ReentrantERC20Token.sol
@@ -19,7 +19,7 @@
pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
import "../../tokens/ERC20Token/ERC20Token.sol";
import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
diff --git a/contracts/core/contracts/tokens/ERC20Token/MintableERC20Token.sol b/contracts/core/contracts/tokens/ERC20Token/MintableERC20Token.sol
index 9dc924422..58bccb5a1 100644
--- a/contracts/core/contracts/tokens/ERC20Token/MintableERC20Token.sol
+++ b/contracts/core/contracts/tokens/ERC20Token/MintableERC20Token.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/SafeMath/SafeMath.sol";
+import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
import "./UnlimitedAllowanceERC20Token.sol";
diff --git a/contracts/core/contracts/tokens/ERC721Token/ERC721Token.sol b/contracts/core/contracts/tokens/ERC721Token/ERC721Token.sol
index 530f080c0..600cee1ab 100644
--- a/contracts/core/contracts/tokens/ERC721Token/ERC721Token.sol
+++ b/contracts/core/contracts/tokens/ERC721Token/ERC721Token.sol
@@ -20,7 +20,7 @@ pragma solidity 0.4.24;
import "./IERC721Token.sol";
import "./IERC721Receiver.sol";
-import "../../utils/SafeMath/SafeMath.sol";
+import "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol";
contract ERC721Token is
diff --git a/contracts/core/package.json b/contracts/core/package.json
index b20b0ef3f..701e1866e 100644
--- a/contracts/core/package.json
+++ b/contracts/core/package.json
@@ -1,6 +1,6 @@
{
"private": true,
- "name": "contracts",
+ "name": "@0x/contracts-core",
"version": "2.1.56",
"engines": {
"node": ">=6.12"
@@ -33,20 +33,19 @@
"lint-contracts": "solhint contracts/**/**/**/**/*.sol"
},
"config": {
- "abis":
- "generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiAssetProxy|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json"
+ "abis": "generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|DutchAuction|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiAssetProxy|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json"
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
- "author": "Amir Bandeali",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/core/README.md",
"devDependencies": {
+ "@0x/contracts-test-utils": "^1.0.0",
"@0x/abi-gen": "^1.0.17",
"@0x/dev-utils": "^1.0.19",
"@0x/sol-compiler": "^1.1.14",
@@ -54,7 +53,6 @@
"@0x/subproviders": "^2.1.6",
"@0x/tslint-config": "^1.0.10",
"@types/bn.js": "^4.11.0",
- "@types/ethereumjs-abi": "^0.6.0",
"@types/lodash": "4.14.104",
"@types/node": "*",
"@types/yargs": "^10.0.0",
@@ -63,6 +61,7 @@
"chai-bignumber": "^2.0.1",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
+ "ethereumjs-abi": "0.6.5",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -75,6 +74,8 @@
"dependencies": {
"@0x/base-contract": "^3.0.8",
"@0x/order-utils": "^3.0.4",
+ "@0x/contracts-multisig": "^1.0.0",
+ "@0x/contracts-utils": "^1.0.0",
"@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6",
@@ -82,10 +83,7 @@
"@types/js-combinatorics": "^0.5.29",
"bn.js": "^4.11.8",
"ethereum-types": "^1.1.2",
- "ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
- "ethers": "~4.0.4",
- "js-combinatorics": "^0.5.3",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/contracts/core/src/artifacts/index.ts b/contracts/core/src/artifacts/index.ts
index 97c1b6209..b925ec87f 100644
--- a/contracts/core/src/artifacts/index.ts
+++ b/contracts/core/src/artifacts/index.ts
@@ -6,6 +6,7 @@ import * as DummyERC721Receiver from '../../generated-artifacts/DummyERC721Recei
import * as DummyERC721Token from '../../generated-artifacts/DummyERC721Token.json';
import * as DummyMultipleReturnERC20Token from '../../generated-artifacts/DummyMultipleReturnERC20Token.json';
import * as DummyNoReturnERC20Token from '../../generated-artifacts/DummyNoReturnERC20Token.json';
+import * as DutchAuction from '../../generated-artifacts/DutchAuction.json';
import * as ERC20Proxy from '../../generated-artifacts/ERC20Proxy.json';
import * as ERC20Token from '../../generated-artifacts/ERC20Token.json';
import * as ERC721Proxy from '../../generated-artifacts/ERC721Proxy.json';
@@ -20,15 +21,11 @@ import * as IValidator from '../../generated-artifacts/IValidator.json';
import * as IWallet from '../../generated-artifacts/IWallet.json';
import * as MixinAuthorizable from '../../generated-artifacts/MixinAuthorizable.json';
import * as MultiAssetProxy from '../../generated-artifacts/MultiAssetProxy.json';
-import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
-import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
import * as OrderValidator from '../../generated-artifacts/OrderValidator.json';
import * as ReentrantERC20Token from '../../generated-artifacts/ReentrantERC20Token.json';
import * as TestAssetProxyDispatcher from '../../generated-artifacts/TestAssetProxyDispatcher.json';
import * as TestAssetProxyOwner from '../../generated-artifacts/TestAssetProxyOwner.json';
-import * as TestConstants from '../../generated-artifacts/TestConstants.json';
import * as TestExchangeInternals from '../../generated-artifacts/TestExchangeInternals.json';
-import * as TestLibBytes from '../../generated-artifacts/TestLibBytes.json';
import * as TestLibs from '../../generated-artifacts/TestLibs.json';
import * as TestSignatureValidator from '../../generated-artifacts/TestSignatureValidator.json';
import * as TestStaticCallReceiver from '../../generated-artifacts/TestStaticCallReceiver.json';
@@ -45,6 +42,7 @@ export const artifacts = {
DummyERC721Token: DummyERC721Token as ContractArtifact,
DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
+ DutchAuction: DutchAuction as ContractArtifact,
ERC20Proxy: ERC20Proxy as ContractArtifact,
ERC20Token: ERC20Token as ContractArtifact,
ERC721Proxy: ERC721Proxy as ContractArtifact,
@@ -59,15 +57,11 @@ export const artifacts = {
InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
- MultiSigWallet: MultiSigWallet as ContractArtifact,
- MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
OrderValidator: OrderValidator as ContractArtifact,
ReentrantERC20Token: ReentrantERC20Token as ContractArtifact,
TestAssetProxyDispatcher: TestAssetProxyDispatcher as ContractArtifact,
TestAssetProxyOwner: TestAssetProxyOwner as ContractArtifact,
- TestConstants: TestConstants as ContractArtifact,
TestExchangeInternals: TestExchangeInternals as ContractArtifact,
- TestLibBytes: TestLibBytes as ContractArtifact,
TestLibs: TestLibs as ContractArtifact,
TestSignatureValidator: TestSignatureValidator as ContractArtifact,
TestStaticCallReceiver: TestStaticCallReceiver as ContractArtifact,
diff --git a/contracts/core/src/wrappers/index.ts b/contracts/core/src/wrappers/index.ts
index 9ca676b56..0a64a4db0 100644
--- a/contracts/core/src/wrappers/index.ts
+++ b/contracts/core/src/wrappers/index.ts
@@ -4,6 +4,7 @@ export * from '../../generated-wrappers/dummy_erc721_receiver';
export * from '../../generated-wrappers/dummy_erc721_token';
export * from '../../generated-wrappers/dummy_multiple_return_erc20_token';
export * from '../../generated-wrappers/dummy_no_return_erc20_token';
+export * from '../../generated-wrappers/dutch_auction';
export * from '../../generated-wrappers/erc20_proxy';
export * from '../../generated-wrappers/erc721_proxy';
export * from '../../generated-wrappers/erc20_token';
@@ -15,15 +16,11 @@ export * from '../../generated-wrappers/i_asset_data';
export * from '../../generated-wrappers/i_asset_proxy';
export * from '../../generated-wrappers/invalid_erc721_receiver';
export * from '../../generated-wrappers/mixin_authorizable';
-export * from '../../generated-wrappers/multi_sig_wallet';
-export * from '../../generated-wrappers/multi_sig_wallet_with_time_lock';
export * from '../../generated-wrappers/order_validator';
export * from '../../generated-wrappers/reentrant_erc20_token';
export * from '../../generated-wrappers/test_asset_proxy_dispatcher';
export * from '../../generated-wrappers/test_asset_proxy_owner';
-export * from '../../generated-wrappers/test_constants';
export * from '../../generated-wrappers/test_exchange_internals';
-export * from '../../generated-wrappers/test_lib_bytes';
export * from '../../generated-wrappers/test_libs';
export * from '../../generated-wrappers/test_signature_validator';
export * from '../../generated-wrappers/test_static_call_receiver';
diff --git a/contracts/core/test/asset_proxy/authorizable.ts b/contracts/core/test/asset_proxy/authorizable.ts
index e21af9b81..853d18be0 100644
--- a/contracts/core/test/asset_proxy/authorizable.ts
+++ b/contracts/core/test/asset_proxy/authorizable.ts
@@ -1,3 +1,11 @@
+import {
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -6,10 +14,6 @@ import * as _ from 'lodash';
import { MixinAuthorizableContract } from '../../generated-wrappers/mixin_authorizable';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/asset_proxy/proxies.ts b/contracts/core/test/asset_proxy/proxies.ts
index 8fa1e602a..2527b0fbf 100644
--- a/contracts/core/test/asset_proxy/proxies.ts
+++ b/contracts/core/test/asset_proxy/proxies.ts
@@ -1,3 +1,13 @@
+import {
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ LogDecoder,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
@@ -16,13 +26,8 @@ import { IAssetDataContract } from '../../generated-wrappers/i_asset_data';
import { IAssetProxyContract } from '../../generated-wrappers/i_asset_proxy';
import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_proxy';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
-import { LogDecoder } from '../utils/log_decoder';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -553,7 +558,7 @@ describe('Asset Transfer Proxies', () => {
erc721Receiver.address,
amount,
);
- const logDecoder = new LogDecoder(web3Wrapper);
+ const logDecoder = new LogDecoder(web3Wrapper, artifacts);
const tx = await logDecoder.getTxWithDecodedLogsAsync(
await web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
diff --git a/contracts/core/test/exchange/core.ts b/contracts/core/test/exchange/core.ts
index 9159b0d8f..fd6b9ee6b 100644
--- a/contracts/core/test/exchange/core.ts
+++ b/contracts/core/test/exchange/core.ts
@@ -1,3 +1,16 @@
+import {
+ chaiSetup,
+ constants,
+ ERC20BalancesByOwner,
+ expectTransactionFailedAsync,
+ getLatestBlockTimestampAsync,
+ increaseTimeAndMineBlockAsync,
+ OrderFactory,
+ OrderStatus,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
@@ -19,16 +32,9 @@ import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_pr
import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token';
import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_static_call_receiver';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
-import { OrderFactory } from '../utils/order_factory';
-import { ERC20BalancesByOwner, OrderStatus } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/exchange/dispatcher.ts b/contracts/core/test/exchange/dispatcher.ts
index 3d3aa42c2..9bc5cbcce 100644
--- a/contracts/core/test/exchange/dispatcher.ts
+++ b/contracts/core/test/exchange/dispatcher.ts
@@ -1,3 +1,12 @@
+import {
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ LogDecoder,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types';
@@ -14,13 +23,8 @@ import {
TestAssetProxyDispatcherContract,
} from '../../generated-wrappers/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
-import { LogDecoder } from '../utils/log_decoder';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -145,7 +149,7 @@ describe('AssetProxyDispatcher', () => {
});
it('should log an event with correct arguments when an asset proxy is registered', async () => {
- const logDecoder = new LogDecoder(web3Wrapper);
+ const logDecoder = new LogDecoder(web3Wrapper, artifacts);
const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
);
diff --git a/contracts/core/test/exchange/fill_order.ts b/contracts/core/test/exchange/fill_order.ts
index 37efaad2b..2bdbe4855 100644
--- a/contracts/core/test/exchange/fill_order.ts
+++ b/contracts/core/test/exchange/fill_order.ts
@@ -1,23 +1,25 @@
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import * as _ from 'lodash';
-
-import { chaiSetup } from '../utils/chai_setup';
-import {
- FillOrderCombinatorialUtils,
- fillOrderCombinatorialUtilsFactoryAsync,
-} from '../utils/fill_order_combinatorial_utils';
import {
AllowanceAmountScenario,
AssetDataScenario,
BalanceAmountScenario,
+ chaiSetup,
ExpirationTimeSecondsScenario,
FeeRecipientAddressScenario,
FillScenario,
OrderAssetAmountScenario,
+ provider,
TakerAssetFillAmountScenario,
TakerScenario,
-} from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
+import { BlockchainLifecycle } from '@0x/dev-utils';
+import * as _ from 'lodash';
+
+import {
+ FillOrderCombinatorialUtils,
+ fillOrderCombinatorialUtilsFactoryAsync,
+} from '../utils/fill_order_combinatorial_utils';
chaiSetup.configure();
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
diff --git a/contracts/core/test/exchange/internal.ts b/contracts/core/test/exchange/internal.ts
index 109be29c6..972f5efb6 100644
--- a/contracts/core/test/exchange/internal.ts
+++ b/contracts/core/test/exchange/internal.ts
@@ -1,3 +1,15 @@
+import {
+ bytes32Values,
+ chaiSetup,
+ constants,
+ FillResults,
+ getRevertReasonOrErrorMessageForSendTransactionAsync,
+ provider,
+ testCombinatoriallyWithReferenceFuncAsync,
+ txDefaults,
+ uint256Values,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { Order, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -6,12 +18,6 @@ import * as _ from 'lodash';
import { TestExchangeInternalsContract } from '../../generated-wrappers/test_exchange_internals';
import { artifacts } from '../../src/artifacts';
-import { getRevertReasonOrErrorMessageForSendTransactionAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { bytes32Values, testCombinatoriallyWithReferenceFuncAsync, uint256Values } from '../utils/combinatorial_utils';
-import { constants } from '../utils/constants';
-import { FillResults } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/exchange/libs.ts b/contracts/core/test/exchange/libs.ts
index 503ef0e0f..44ff6a844 100644
--- a/contracts/core/test/exchange/libs.ts
+++ b/contracts/core/test/exchange/libs.ts
@@ -1,17 +1,20 @@
+import {
+ addressUtils,
+ chaiSetup,
+ constants,
+ OrderFactory,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
-import { TestConstantsContract } from '../../generated-wrappers/test_constants';
import { TestLibsContract } from '../../generated-wrappers/test_libs';
import { artifacts } from '../../src/artifacts';
-import { addressUtils } from '../utils/address_utils';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { OrderFactory } from '../utils/order_factory';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -22,7 +25,6 @@ describe('Exchange libs', () => {
let signedOrder: SignedOrder;
let orderFactory: OrderFactory;
let libs: TestLibsContract;
- let testConstants: TestConstantsContract;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -34,11 +36,6 @@ describe('Exchange libs', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const makerAddress = accounts[0];
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
- testConstants = await TestConstantsContract.deployFrom0xArtifactAsync(
- artifacts.TestConstants,
- provider,
- txDefaults,
- );
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
@@ -58,15 +55,6 @@ describe('Exchange libs', () => {
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
-
- describe('LibConstants', () => {
- describe('ZRX_ASSET_DATA', () => {
- it('should have the correct ZRX_ASSET_DATA', async () => {
- const isValid = await testConstants.assertValidZrxAssetData.callAsync();
- expect(isValid).to.be.equal(true);
- });
- });
- });
// Note(albrow): These tests are designed to be supplemental to the
// combinatorial tests in test/exchange/internal. They test specific edge
// cases that are not covered by the combinatorial tests.
diff --git a/contracts/core/test/exchange/match_orders.ts b/contracts/core/test/exchange/match_orders.ts
index eea9992d9..0e841b359 100644
--- a/contracts/core/test/exchange/match_orders.ts
+++ b/contracts/core/test/exchange/match_orders.ts
@@ -1,3 +1,14 @@
+import {
+ chaiSetup,
+ constants,
+ ERC20BalancesByOwner,
+ ERC721TokenIdsByOwner,
+ expectTransactionFailedAsync,
+ OrderFactory,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
@@ -14,16 +25,10 @@ import { ExchangeContract } from '../../generated-wrappers/exchange';
import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token';
import { TestExchangeInternalsContract } from '../../generated-wrappers/test_exchange_internals';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { MatchOrderTester } from '../utils/match_order_tester';
-import { OrderFactory } from '../utils/order_factory';
-import { ERC20BalancesByOwner, ERC721TokenIdsByOwner } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
chaiSetup.configure();
diff --git a/contracts/core/test/exchange/signature_validator.ts b/contracts/core/test/exchange/signature_validator.ts
index 756c72766..b84a488a1 100644
--- a/contracts/core/test/exchange/signature_validator.ts
+++ b/contracts/core/test/exchange/signature_validator.ts
@@ -1,3 +1,14 @@
+import {
+ addressUtils,
+ chaiSetup,
+ constants,
+ expectContractCallFailedAsync,
+ LogDecoder,
+ OrderFactory,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
@@ -13,13 +24,6 @@ import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_st
import { ValidatorContract } from '../../generated-wrappers/validator';
import { WalletContract } from '../../generated-wrappers/wallet';
import { artifacts } from '../../src/artifacts';
-import { addressUtils } from '../utils/address_utils';
-import { expectContractCallFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { LogDecoder } from '../utils/log_decoder';
-import { OrderFactory } from '../utils/order_factory';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -73,7 +77,7 @@ describe('MixinSignatureValidator', () => {
provider,
txDefaults,
);
- signatureValidatorLogDecoder = new LogDecoder(web3Wrapper);
+ signatureValidatorLogDecoder = new LogDecoder(web3Wrapper, artifacts);
await web3Wrapper.awaitTransactionSuccessAsync(
await signatureValidator.setSignatureValidatorApproval.sendTransactionAsync(testValidator.address, true, {
from: signerAddress,
diff --git a/contracts/core/test/exchange/transactions.ts b/contracts/core/test/exchange/transactions.ts
index 1b5eef295..c4086d9be 100644
--- a/contracts/core/test/exchange/transactions.ts
+++ b/contracts/core/test/exchange/transactions.ts
@@ -1,3 +1,16 @@
+import {
+ chaiSetup,
+ constants,
+ ERC20BalancesByOwner,
+ expectTransactionFailedAsync,
+ OrderFactory,
+ orderUtils,
+ provider,
+ SignedTransaction,
+ TransactionFactory,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
import { OrderWithoutExchangeAddress, RevertReason, SignedOrder } from '@0x/types';
@@ -11,16 +24,8 @@ import { ExchangeContract } from '../../generated-wrappers/exchange';
import { ExchangeWrapperContract } from '../../generated-wrappers/exchange_wrapper';
import { WhitelistContract } from '../../generated-wrappers/whitelist';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
-import { OrderFactory } from '../utils/order_factory';
-import { orderUtils } from '../utils/order_utils';
-import { TransactionFactory } from '../utils/transaction_factory';
-import { ERC20BalancesByOwner, SignedTransaction } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/exchange/wrapper.ts b/contracts/core/test/exchange/wrapper.ts
index 6b660aac5..17cb7a3bb 100644
--- a/contracts/core/test/exchange/wrapper.ts
+++ b/contracts/core/test/exchange/wrapper.ts
@@ -1,3 +1,16 @@
+import {
+ chaiSetup,
+ constants,
+ ERC20BalancesByOwner,
+ expectTransactionFailedAsync,
+ getLatestBlockTimestampAsync,
+ increaseTimeAndMineBlockAsync,
+ OrderFactory,
+ OrderStatus,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types';
@@ -13,16 +26,9 @@ import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
import { ExchangeContract } from '../../generated-wrappers/exchange';
import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from '../utils/assertions';
-import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
-import { OrderFactory } from '../utils/order_factory';
-import { ERC20BalancesByOwner, OrderStatus } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/extensions/dutch_auction.ts b/contracts/core/test/extensions/dutch_auction.ts
new file mode 100644
index 000000000..6bed222f4
--- /dev/null
+++ b/contracts/core/test/extensions/dutch_auction.ts
@@ -0,0 +1,491 @@
+import {
+ chaiSetup,
+ constants,
+ ContractName,
+ ERC20BalancesByOwner,
+ expectTransactionFailedAsync,
+ getLatestBlockTimestampAsync,
+ OrderFactory,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
+import { BlockchainLifecycle } from '@0x/dev-utils';
+import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
+import { RevertReason, SignedOrder } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
+import * as chai from 'chai';
+import ethAbi = require('ethereumjs-abi');
+import * as ethUtil from 'ethereumjs-util';
+import * as _ from 'lodash';
+
+import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
+import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_token';
+import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
+import { ExchangeContract } from '../../generated-wrappers/exchange';
+import { WETH9Contract } from '../../generated-wrappers/weth9';
+import { artifacts } from '../../src/artifacts';
+import { ERC20Wrapper } from '../utils/erc20_wrapper';
+import { ERC721Wrapper } from '../utils/erc721_wrapper';
+import { ExchangeWrapper } from '../utils/exchange_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+const DECIMALS_DEFAULT = 18;
+
+describe(ContractName.DutchAuction, () => {
+ let makerAddress: string;
+ let owner: string;
+ let takerAddress: string;
+ let feeRecipientAddress: string;
+ let defaultMakerAssetAddress: string;
+
+ let zrxToken: DummyERC20TokenContract;
+ let erc20TokenA: DummyERC20TokenContract;
+ let erc721Token: DummyERC721TokenContract;
+ let dutchAuctionContract: DutchAuctionContract;
+ let wethContract: WETH9Contract;
+
+ let sellerOrderFactory: OrderFactory;
+ let buyerOrderFactory: OrderFactory;
+ let erc20Wrapper: ERC20Wrapper;
+ let erc20Balances: ERC20BalancesByOwner;
+ let currentBlockTimestamp: number;
+ let auctionBeginTimeSeconds: BigNumber;
+ let auctionEndTimeSeconds: BigNumber;
+ let auctionBeginAmount: BigNumber;
+ let auctionEndAmount: BigNumber;
+ let sellOrder: SignedOrder;
+ let buyOrder: SignedOrder;
+ let erc721MakerAssetIds: BigNumber[];
+ const tenMinutesInSeconds = 10 * 60;
+
+ async function increaseTimeAsync(): Promise<void> {
+ const timestampBefore = await getLatestBlockTimestampAsync();
+ await web3Wrapper.increaseTimeAsync(5);
+ const timestampAfter = await getLatestBlockTimestampAsync();
+ // HACK send some transactions when a time increase isn't supported
+ if (timestampAfter === timestampBefore) {
+ await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
+ }
+ }
+
+ function extendMakerAssetData(makerAssetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string {
+ return ethUtil.bufferToHex(
+ Buffer.concat([
+ ethUtil.toBuffer(makerAssetData),
+ ethUtil.toBuffer(
+ (ethAbi as any).rawEncode(
+ ['uint256', 'uint256'],
+ [beginTimeSeconds.toString(), beginAmount.toString()],
+ ),
+ ),
+ ]),
+ );
+ }
+
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
+
+ erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
+
+ const numDummyErc20ToDeploy = 2;
+ [erc20TokenA, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ numDummyErc20ToDeploy,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
+ const erc20Proxy = await erc20Wrapper.deployProxyAsync();
+ await erc20Wrapper.setBalancesAndAllowancesAsync();
+
+ const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
+ [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
+ const erc721Proxy = await erc721Wrapper.deployProxyAsync();
+ await erc721Wrapper.setBalancesAndAllowancesAsync();
+ const erc721Balances = await erc721Wrapper.getBalancesAsync();
+ erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
+
+ wethContract = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults);
+ erc20Wrapper.addDummyTokenContract(wethContract as any);
+
+ const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
+ const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
+ artifacts.Exchange,
+ provider,
+ txDefaults,
+ zrxAssetData,
+ );
+ const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
+
+ await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
+ from: owner,
+ });
+ await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
+ from: owner,
+ });
+
+ const dutchAuctionInstance = await DutchAuctionContract.deployFrom0xArtifactAsync(
+ artifacts.DutchAuction,
+ provider,
+ txDefaults,
+ exchangeInstance.address,
+ );
+ dutchAuctionContract = new DutchAuctionContract(
+ dutchAuctionInstance.abi,
+ dutchAuctionInstance.address,
+ provider,
+ );
+
+ defaultMakerAssetAddress = erc20TokenA.address;
+ const defaultTakerAssetAddress = wethContract.address;
+
+ // Set up taker WETH balance and allowance
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await wethContract.deposit.sendTransactionAsync({
+ from: takerAddress,
+ value: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
+ }),
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await wethContract.approve.sendTransactionAsync(
+ erc20Proxy.address,
+ constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
+ { from: takerAddress },
+ ),
+ );
+ web3Wrapper.abiDecoder.addABI(exchangeInstance.abi);
+ web3Wrapper.abiDecoder.addABI(zrxToken.abi);
+ erc20Wrapper.addTokenOwnerAddress(dutchAuctionContract.address);
+
+ currentBlockTimestamp = await getLatestBlockTimestampAsync();
+ // Default auction begins 10 minutes ago
+ auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp).minus(tenMinutesInSeconds);
+ // Default auction ends 10 from now
+ auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds);
+ auctionBeginAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT);
+ auctionEndAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT);
+
+ // Default sell order and buy order are exact mirrors
+ const sellerDefaultOrderParams = {
+ salt: generatePseudoRandomSalt(),
+ exchangeAddress: exchangeInstance.address,
+ makerAddress,
+ feeRecipientAddress,
+ // taker address or sender address should be set to the ducth auction contract
+ takerAddress: dutchAuctionContract.address,
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
+ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
+ takerAssetAmount: auctionEndAmount,
+ expirationTimeSeconds: auctionEndTimeSeconds,
+ makerFee: constants.ZERO_AMOUNT,
+ takerFee: constants.ZERO_AMOUNT,
+ };
+ // Default buy order is for the auction begin price
+ const buyerDefaultOrderParams = {
+ ...sellerDefaultOrderParams,
+ makerAddress: takerAddress,
+ makerAssetData: sellerDefaultOrderParams.takerAssetData,
+ takerAssetData: sellerDefaultOrderParams.makerAssetData,
+ makerAssetAmount: auctionBeginAmount,
+ takerAssetAmount: sellerDefaultOrderParams.makerAssetAmount,
+ };
+ const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
+ const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
+ sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
+ buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ erc20Balances = await erc20Wrapper.getBalancesAsync();
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync();
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('matchOrders', () => {
+ it('should be worth the begin price at the begining of the auction', async () => {
+ auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2);
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ });
+ const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount);
+ expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
+ });
+ it('should be be worth the end price at the end of the auction', async () => {
+ auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
+ auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ expirationTimeSeconds: auctionEndTimeSeconds,
+ });
+ const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount);
+ expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
+ });
+ it('should match orders at current amount and send excess to buyer', async () => {
+ const beforeAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync({
+ makerAssetAmount: beforeAuctionDetails.currentAmount.times(2),
+ });
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ );
+ const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal(
+ constants.ZERO_AMOUNT,
+ );
+ // HACK gte used here due to a bug in ganache where the timestamp can change
+ // between multiple calls to the same block. Which can move the amount in our case
+ // ref: https://github.com/trufflesuite/ganache-core/issues/111
+ expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
+ erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
+ );
+ expect(newBalances[takerAddress][wethContract.address]).to.be.bignumber.gte(
+ erc20Balances[takerAddress][wethContract.address].minus(beforeAuctionDetails.currentAmount),
+ );
+ });
+ it('should have valid getAuctionDetails at some block in the future', async () => {
+ let auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ const beforeAmount = auctionDetails.currentAmount;
+ await increaseTimeAsync();
+ auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ const currentAmount = auctionDetails.currentAmount;
+ expect(beforeAmount).to.be.bignumber.greaterThan(currentAmount);
+
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync({
+ makerAssetAmount: currentAmount,
+ });
+ const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ // HACK geth seems to miscalculate the gas required intermittently
+ gas: 400000,
+ },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.equal(
+ erc20Balances[makerAddress][wethContract.address].plus(currentAmount),
+ );
+ });
+ it('maker fees on sellOrder are paid to the fee receipient', async () => {
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ makerFee: new BigNumber(1),
+ });
+ const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash);
+ const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
+ erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
+ );
+ expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[feeRecipientAddress][zrxToken.address].plus(sellOrder.makerFee),
+ );
+ });
+ it('maker fees on buyOrder are paid to the fee receipient', async () => {
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync({
+ makerFee: new BigNumber(1),
+ });
+ const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
+ erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
+ );
+ expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
+ erc20Balances[feeRecipientAddress][zrxToken.address].plus(buyOrder.makerFee),
+ );
+ });
+ it('should revert when auction expires', async () => {
+ auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
+ auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ expirationTimeSeconds: auctionEndTimeSeconds,
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ });
+ return expectTransactionFailedAsync(
+ dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ RevertReason.AuctionExpired,
+ );
+ });
+ it('cannot be filled for less than the current price', async () => {
+ await increaseTimeAsync();
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync({
+ makerAssetAmount: sellOrder.takerAssetAmount,
+ });
+ return expectTransactionFailedAsync(
+ dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ RevertReason.AuctionInvalidAmount,
+ );
+ });
+ it('auction begin amount must be higher than final amount ', async () => {
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ takerAssetAmount: auctionBeginAmount.plus(1),
+ });
+ return expectTransactionFailedAsync(
+ dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ RevertReason.AuctionInvalidAmount,
+ );
+ });
+ it('begin time is less than end time', async () => {
+ auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds);
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ expirationTimeSeconds: auctionEndTimeSeconds,
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ });
+ return expectTransactionFailedAsync(
+ dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ RevertReason.AuctionInvalidBeginTime,
+ );
+ });
+ it('asset data contains auction parameters', async () => {
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ });
+ return expectTransactionFailedAsync(
+ dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ RevertReason.InvalidAssetData,
+ );
+ });
+ describe('ERC721', () => {
+ it('should match orders when ERC721', async () => {
+ const makerAssetId = erc721MakerAssetIds[0];
+ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
+ makerAssetAmount: new BigNumber(1),
+ makerAssetData: extendMakerAssetData(
+ assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ auctionBeginTimeSeconds,
+ auctionBeginAmount,
+ ),
+ });
+ buyOrder = await buyerOrderFactory.newSignedOrderAsync({
+ takerAssetAmount: new BigNumber(1),
+ takerAssetData: sellOrder.makerAssetData,
+ });
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await dutchAuctionContract.matchOrders.sendTransactionAsync(
+ buyOrder,
+ sellOrder,
+ buyOrder.signature,
+ sellOrder.signature,
+ {
+ from: takerAddress,
+ },
+ ),
+ );
+ const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ // HACK gte used here due to a bug in ganache where the timestamp can change
+ // between multiple calls to the same block. Which can move the amount in our case
+ // ref: https://github.com/trufflesuite/ganache-core/issues/111
+ expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
+ erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
+ );
+ const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
+ expect(newOwner).to.be.bignumber.equal(takerAddress);
+ });
+ });
+ });
+});
diff --git a/contracts/core/test/extensions/forwarder.ts b/contracts/core/test/extensions/forwarder.ts
index c006be0fe..44ad4d6ff 100644
--- a/contracts/core/test/extensions/forwarder.ts
+++ b/contracts/core/test/extensions/forwarder.ts
@@ -1,3 +1,16 @@
+import {
+ chaiSetup,
+ constants,
+ ContractName,
+ ERC20BalancesByOwner,
+ expectContractCreationFailedAsync,
+ expectTransactionFailedAsync,
+ OrderFactory,
+ provider,
+ sendTransactionResult,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types';
@@ -12,20 +25,10 @@ import { ExchangeContract } from '../../generated-wrappers/exchange';
import { ForwarderContract } from '../../generated-wrappers/forwarder';
import { WETH9Contract } from '../../generated-wrappers/weth9';
import { artifacts } from '../../src/artifacts';
-import {
- expectContractCreationFailedAsync,
- expectTransactionFailedAsync,
- sendTransactionResult,
-} from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { ForwarderWrapper } from '../utils/forwarder_wrapper';
-import { OrderFactory } from '../utils/order_factory';
-import { ContractName, ERC20BalancesByOwner } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/extensions/order_validator.ts b/contracts/core/test/extensions/order_validator.ts
index 37d7c4c5a..3dbe76f6e 100644
--- a/contracts/core/test/extensions/order_validator.ts
+++ b/contracts/core/test/extensions/order_validator.ts
@@ -1,3 +1,12 @@
+import {
+ chaiSetup,
+ constants,
+ OrderFactory,
+ OrderStatus,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types';
@@ -12,14 +21,9 @@ import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
import { ExchangeContract } from '../../generated-wrappers/exchange';
import { OrderValidatorContract } from '../../generated-wrappers/order_validator';
import { artifacts } from '../../src/artifacts';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
-import { OrderFactory } from '../utils/order_factory';
-import { OrderStatus } from '../utils/types';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/global_hooks.ts b/contracts/core/test/global_hooks.ts
index 2e9ac9e21..f8ace376a 100644
--- a/contracts/core/test/global_hooks.ts
+++ b/contracts/core/test/global_hooks.ts
@@ -1,8 +1,9 @@
import { env, EnvVars } from '@0x/dev-utils';
-import { coverage } from './utils/coverage';
-import { profiler } from './utils/profiler';
-
+import { coverage, profiler, provider } from '@0x/contracts-test-utils';
+before('start web3 provider', () => {
+ provider.start();
+});
after('generate coverage report', async () => {
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
@@ -12,4 +13,5 @@ after('generate coverage report', async () => {
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
await profilerSubprovider.writeProfilerOutputAsync();
}
+ provider.stop();
});
diff --git a/contracts/core/test/multisig/asset_proxy_owner.ts b/contracts/core/test/multisig/asset_proxy_owner.ts
index 087152316..daebfb7fb 100644
--- a/contracts/core/test/multisig/asset_proxy_owner.ts
+++ b/contracts/core/test/multisig/asset_proxy_owner.ts
@@ -1,3 +1,16 @@
+import {
+ chaiSetup,
+ constants,
+ expectContractCallFailedAsync,
+ expectContractCreationFailedAsync,
+ expectTransactionFailedAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ increaseTimeAndMineBlockAsync,
+ provider,
+ sendTransactionResult,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -14,18 +27,7 @@ import {
import { MixinAuthorizableContract } from '../../generated-wrappers/mixin_authorizable';
import { TestAssetProxyOwnerContract } from '../../generated-wrappers/test_asset_proxy_owner';
import { artifacts } from '../../src/artifacts';
-import {
- expectContractCallFailedAsync,
- expectContractCreationFailedAsync,
- expectTransactionFailedAsync,
- expectTransactionFailedWithoutReasonAsync,
- sendTransactionResult,
-} from '../utils/assertions';
-import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { MultiSigWrapper } from '../utils/multi_sig_wrapper';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
+import { AssetProxyOwnerWrapper } from '../utils/asset_proxy_owner_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -41,7 +43,7 @@ describe('AssetProxyOwner', () => {
let erc20Proxy: MixinAuthorizableContract;
let erc721Proxy: MixinAuthorizableContract;
let testAssetProxyOwner: TestAssetProxyOwnerContract;
- let multiSigWrapper: MultiSigWrapper;
+ let assetProxyOwnerWrapper: AssetProxyOwnerWrapper;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -75,7 +77,7 @@ describe('AssetProxyOwner', () => {
REQUIRED_APPROVALS,
SECONDS_TIME_LOCKED,
);
- multiSigWrapper = new MultiSigWrapper(testAssetProxyOwner, provider);
+ assetProxyOwnerWrapper = new AssetProxyOwnerWrapper(testAssetProxyOwner, provider);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferOwnership.sendTransactionAsync(testAssetProxyOwner.address, {
from: initialOwner,
@@ -172,7 +174,7 @@ describe('AssetProxyOwner', () => {
addressToRegister,
isRegistered,
);
- const submitTxRes = await multiSigWrapper.submitTransactionAsync(
+ const submitTxRes = await assetProxyOwnerWrapper.submitTransactionAsync(
testAssetProxyOwner.address,
registerAssetProxyData,
owners[0],
@@ -181,10 +183,10 @@ describe('AssetProxyOwner', () => {
const log = submitTxRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = log.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
- const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]);
+ const executeTxRes = await assetProxyOwnerWrapper.executeTransactionAsync(txId, owners[0]);
const registerLog = executeTxRes.logs[0] as LogWithDecodedArgs<
AssetProxyOwnerAssetProxyRegistrationEventArgs
>;
@@ -204,7 +206,7 @@ describe('AssetProxyOwner', () => {
addressToRegister,
isRegistered,
);
- const submitTxRes = await multiSigWrapper.submitTransactionAsync(
+ const submitTxRes = await assetProxyOwnerWrapper.submitTransactionAsync(
testAssetProxyOwner.address,
registerAssetProxyData,
owners[0],
@@ -212,10 +214,10 @@ describe('AssetProxyOwner', () => {
const log = submitTxRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = log.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
- const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]);
+ const executeTxRes = await assetProxyOwnerWrapper.executeTransactionAsync(txId, owners[0]);
const failureLog = executeTxRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerExecutionFailureEventArgs>;
expect(failureLog.args.transactionId).to.be.bignumber.equal(txId);
@@ -237,7 +239,7 @@ describe('AssetProxyOwner', () => {
addressToRegister,
isRegistered,
);
- const registerAssetProxySubmitRes = await multiSigWrapper.submitTransactionAsync(
+ const registerAssetProxySubmitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
testAssetProxyOwner.address,
registerAssetProxyData,
owners[0],
@@ -247,12 +249,12 @@ describe('AssetProxyOwner', () => {
>;
const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(authorized);
- const erc20AddAuthorizedAddressSubmitRes = await multiSigWrapper.submitTransactionAsync(
+ const erc20AddAuthorizedAddressSubmitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
addAuthorizedAddressData,
owners[0],
);
- const erc721AddAuthorizedAddressSubmitRes = await multiSigWrapper.submitTransactionAsync(
+ const erc721AddAuthorizedAddressSubmitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc721Proxy.address,
addAuthorizedAddressData,
owners[0],
@@ -267,15 +269,15 @@ describe('AssetProxyOwner', () => {
const erc20AddAuthorizedAddressTxId = erc20AddAuthorizedAddressSubmitLog.args.transactionId;
const erc721AddAuthorizedAddressTxId = erc721AddAuthorizedAddressSubmitLog.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(registerAssetProxyTxId, owners[1]);
- await multiSigWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]);
- await multiSigWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(registerAssetProxyTxId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]);
await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
- await multiSigWrapper.executeTransactionAsync(registerAssetProxyTxId, owners[0]);
- await multiSigWrapper.executeTransactionAsync(erc20AddAuthorizedAddressTxId, owners[0], {
+ await assetProxyOwnerWrapper.executeTransactionAsync(registerAssetProxyTxId, owners[0]);
+ await assetProxyOwnerWrapper.executeTransactionAsync(erc20AddAuthorizedAddressTxId, owners[0], {
gas: constants.MAX_EXECUTE_TRANSACTION_GAS,
});
- await multiSigWrapper.executeTransactionAsync(erc721AddAuthorizedAddressTxId, owners[0], {
+ await assetProxyOwnerWrapper.executeTransactionAsync(erc721AddAuthorizedAddressTxId, owners[0], {
gas: constants.MAX_EXECUTE_TRANSACTION_GAS,
});
});
@@ -285,7 +287,7 @@ describe('AssetProxyOwner', () => {
const notRemoveAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(
authorized,
);
- const submitTxRes = await multiSigWrapper.submitTransactionAsync(
+ const submitTxRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
notRemoveAuthorizedAddressData,
owners[0],
@@ -303,7 +305,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc20Index,
);
- const submitTxRes = await multiSigWrapper.submitTransactionAsync(
+ const submitTxRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -321,7 +323,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc721Index,
);
- const submitTxRes = await multiSigWrapper.submitTransactionAsync(
+ const submitTxRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc721Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -341,7 +343,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc20Index,
);
- const res = await multiSigWrapper.submitTransactionAsync(
+ const res = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -362,7 +364,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc721Index,
);
- const res = await multiSigWrapper.submitTransactionAsync(
+ const res = await assetProxyOwnerWrapper.submitTransactionAsync(
erc721Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -370,7 +372,7 @@ describe('AssetProxyOwner', () => {
const log = res.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = log.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
return expectTransactionFailedAsync(
testAssetProxyOwner.executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, {
@@ -385,7 +387,7 @@ describe('AssetProxyOwner', () => {
const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(
newAuthorized,
);
- const res = await multiSigWrapper.submitTransactionAsync(
+ const res = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
addAuthorizedAddressData,
owners[0],
@@ -393,7 +395,7 @@ describe('AssetProxyOwner', () => {
const log = res.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = log.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
return expectTransactionFailedAsync(
testAssetProxyOwner.executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, {
@@ -411,7 +413,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc20Index,
);
- const submitRes = await multiSigWrapper.submitTransactionAsync(
+ const submitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -419,9 +421,12 @@ describe('AssetProxyOwner', () => {
const submitLog = submitRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = submitLog.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
- const execRes = await multiSigWrapper.executeRemoveAuthorizedAddressAtIndexAsync(txId, owners[0]);
+ const execRes = await assetProxyOwnerWrapper.executeRemoveAuthorizedAddressAtIndexAsync(
+ txId,
+ owners[0],
+ );
const execLog = execRes.logs[1] as LogWithDecodedArgs<AssetProxyOwnerExecutionEventArgs>;
expect(execLog.args.transactionId).to.be.bignumber.equal(txId);
@@ -441,7 +446,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc20Index,
);
- const submitRes = await multiSigWrapper.submitTransactionAsync(
+ const submitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -449,9 +454,9 @@ describe('AssetProxyOwner', () => {
const submitLog = submitRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = submitLog.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
- const execRes = await multiSigWrapper.executeRemoveAuthorizedAddressAtIndexAsync(txId, notOwner);
+ const execRes = await assetProxyOwnerWrapper.executeRemoveAuthorizedAddressAtIndexAsync(txId, notOwner);
const execLog = execRes.logs[1] as LogWithDecodedArgs<AssetProxyOwnerExecutionEventArgs>;
expect(execLog.args.transactionId).to.be.bignumber.equal(txId);
@@ -468,7 +473,7 @@ describe('AssetProxyOwner', () => {
authorized,
erc20Index,
);
- const submitRes = await multiSigWrapper.submitTransactionAsync(
+ const submitRes = await assetProxyOwnerWrapper.submitTransactionAsync(
erc20Proxy.address,
removeAuthorizedAddressAtIndexData,
owners[0],
@@ -476,9 +481,12 @@ describe('AssetProxyOwner', () => {
const submitLog = submitRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const txId = submitLog.args.transactionId;
- await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
+ await assetProxyOwnerWrapper.confirmTransactionAsync(txId, owners[1]);
- const execRes = await multiSigWrapper.executeRemoveAuthorizedAddressAtIndexAsync(txId, owners[0]);
+ const execRes = await assetProxyOwnerWrapper.executeRemoveAuthorizedAddressAtIndexAsync(
+ txId,
+ owners[0],
+ );
const execLog = execRes.logs[1] as LogWithDecodedArgs<AssetProxyOwnerExecutionEventArgs>;
expect(execLog.args.transactionId).to.be.bignumber.equal(txId);
@@ -495,4 +503,4 @@ describe('AssetProxyOwner', () => {
});
});
});
-// tslint:enable:no-unnecessary-type-assertion
+// tslint:disable-line max-file-line-count
diff --git a/contracts/core/test/tokens/erc721_token.ts b/contracts/core/test/tokens/erc721_token.ts
index 72407748f..3b0a5f001 100644
--- a/contracts/core/test/tokens/erc721_token.ts
+++ b/contracts/core/test/tokens/erc721_token.ts
@@ -1,3 +1,13 @@
+import {
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ LogDecoder,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -14,11 +24,6 @@ import {
} from '../../generated-wrappers/dummy_erc721_token';
import { InvalidERC721ReceiverContract } from '../../generated-wrappers/invalid_erc721_receiver';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { LogDecoder } from '../utils/log_decoder';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -53,7 +58,7 @@ describe('ERC721Token', () => {
provider,
txDefaults,
);
- logDecoder = new LogDecoder(web3Wrapper);
+ logDecoder = new LogDecoder(web3Wrapper, artifacts);
await web3Wrapper.awaitTransactionSuccessAsync(
await token.mint.sendTransactionAsync(owner, tokenId, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
diff --git a/contracts/core/test/tokens/unlimited_allowance_token.ts b/contracts/core/test/tokens/unlimited_allowance_token.ts
index ea5a50522..c3e4072c5 100644
--- a/contracts/core/test/tokens/unlimited_allowance_token.ts
+++ b/contracts/core/test/tokens/unlimited_allowance_token.ts
@@ -1,3 +1,11 @@
+import {
+ chaiSetup,
+ constants,
+ expectContractCallFailedAsync,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -5,10 +13,6 @@ import * as chai from 'chai';
import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
import { artifacts } from '../../src/artifacts';
-import { expectContractCallFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/tokens/weth9.ts b/contracts/core/test/tokens/weth9.ts
index 9a31dc3f2..225481904 100644
--- a/contracts/core/test/tokens/weth9.ts
+++ b/contracts/core/test/tokens/weth9.ts
@@ -1,3 +1,12 @@
+import {
+ chaiSetup,
+ constants,
+ expectInsufficientFundsAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@@ -5,10 +14,6 @@ import * as chai from 'chai';
import { WETH9Contract } from '../../generated-wrappers/weth9';
import { artifacts } from '../../src/artifacts';
-import { expectInsufficientFundsAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/tokens/zrx_token.ts b/contracts/core/test/tokens/zrx_token.ts
index cab62c205..6bc5e164c 100644
--- a/contracts/core/test/tokens/zrx_token.ts
+++ b/contracts/core/test/tokens/zrx_token.ts
@@ -1,3 +1,4 @@
+import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@@ -5,9 +6,6 @@ import * as chai from 'chai';
import { ZRXTokenContract } from '../../generated-wrappers/zrx_token';
import { artifacts } from '../../src/artifacts';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/utils/asset_proxy_owner_wrapper.ts b/contracts/core/test/utils/asset_proxy_owner_wrapper.ts
new file mode 100644
index 000000000..d5aaaf519
--- /dev/null
+++ b/contracts/core/test/utils/asset_proxy_owner_wrapper.ts
@@ -0,0 +1,69 @@
+import { LogDecoder } from '@0x/contracts-test-utils';
+import { BigNumber } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
+import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
+import * as _ from 'lodash';
+
+import { AssetProxyOwnerContract } from '../../generated-wrappers/asset_proxy_owner';
+import { artifacts } from '../../src/artifacts';
+
+export class AssetProxyOwnerWrapper {
+ private readonly _assetProxyOwner: AssetProxyOwnerContract;
+ private readonly _web3Wrapper: Web3Wrapper;
+ private readonly _logDecoder: LogDecoder;
+ constructor(assetproxyOwnerContract: AssetProxyOwnerContract, provider: Provider) {
+ this._assetProxyOwner = assetproxyOwnerContract;
+ this._web3Wrapper = new Web3Wrapper(provider);
+ this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
+ }
+ public async submitTransactionAsync(
+ destination: string,
+ data: string,
+ from: string,
+ opts: { value?: BigNumber } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const value = _.isUndefined(opts.value) ? new BigNumber(0) : opts.value;
+ const txHash = await this._assetProxyOwner.submitTransaction.sendTransactionAsync(destination, value, data, {
+ from,
+ });
+ const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
+ return tx;
+ }
+ public async confirmTransactionAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
+ const txHash = await this._assetProxyOwner.confirmTransaction.sendTransactionAsync(txId, { from });
+ const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
+ return tx;
+ }
+ public async revokeConfirmationAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
+ const txHash = await this._assetProxyOwner.revokeConfirmation.sendTransactionAsync(txId, { from });
+ const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
+ return tx;
+ }
+ public async executeTransactionAsync(
+ txId: BigNumber,
+ from: string,
+ opts: { gas?: number } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const txHash = await this._assetProxyOwner.executeTransaction.sendTransactionAsync(txId, {
+ from,
+ gas: opts.gas,
+ });
+ const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
+ return tx;
+ }
+ public async executeRemoveAuthorizedAddressAtIndexAsync(
+ txId: BigNumber,
+ from: string,
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const txHash = await (this
+ ._assetProxyOwner as AssetProxyOwnerContract).executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(
+ txId,
+ {
+ from,
+ },
+ );
+ const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
+ return tx;
+ }
+}
diff --git a/contracts/core/test/utils/asset_wrapper.ts b/contracts/core/test/utils/asset_wrapper.ts
index 4e7696066..e4090ad74 100644
--- a/contracts/core/test/utils/asset_wrapper.ts
+++ b/contracts/core/test/utils/asset_wrapper.ts
@@ -1,10 +1,9 @@
+import { AbstractAssetWrapper, constants } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber, errorUtils } from '@0x/utils';
import * as _ from 'lodash';
-import { AbstractAssetWrapper } from './abstract_asset_wrapper';
-import { constants } from './constants';
import { ERC20Wrapper } from './erc20_wrapper';
import { ERC721Wrapper } from './erc721_wrapper';
diff --git a/contracts/core/test/utils/erc20_wrapper.ts b/contracts/core/test/utils/erc20_wrapper.ts
index c281a2abf..d6210646c 100644
--- a/contracts/core/test/utils/erc20_wrapper.ts
+++ b/contracts/core/test/utils/erc20_wrapper.ts
@@ -1,3 +1,4 @@
+import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@@ -8,10 +9,6 @@ import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_to
import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy';
import { artifacts } from '../../src/artifacts';
-import { constants } from './constants';
-import { ERC20BalancesByOwner } from './types';
-import { txDefaults } from './web3_wrapper';
-
export class ERC20Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
diff --git a/contracts/core/test/utils/erc721_wrapper.ts b/contracts/core/test/utils/erc721_wrapper.ts
index e9da553d0..b5ae34e60 100644
--- a/contracts/core/test/utils/erc721_wrapper.ts
+++ b/contracts/core/test/utils/erc721_wrapper.ts
@@ -1,3 +1,4 @@
+import { constants, ERC721TokenIdsByOwner, txDefaults } from '@0x/contracts-test-utils';
import { generatePseudoRandomSalt } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@@ -8,10 +9,6 @@ import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_
import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
import { artifacts } from '../../src/artifacts';
-import { constants } from './constants';
-import { ERC721TokenIdsByOwner } from './types';
-import { txDefaults } from './web3_wrapper';
-
export class ERC721Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
diff --git a/contracts/core/test/utils/exchange_wrapper.ts b/contracts/core/test/utils/exchange_wrapper.ts
index c28989d3f..2a24b880f 100644
--- a/contracts/core/test/utils/exchange_wrapper.ts
+++ b/contracts/core/test/utils/exchange_wrapper.ts
@@ -1,14 +1,18 @@
+import {
+ FillResults,
+ formatters,
+ LogDecoder,
+ OrderInfo,
+ orderUtils,
+ SignedTransaction,
+} from '@0x/contracts-test-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { ExchangeContract } from '../../generated-wrappers/exchange';
-
-import { formatters } from './formatters';
-import { LogDecoder } from './log_decoder';
-import { orderUtils } from './order_utils';
-import { FillResults, OrderInfo, SignedTransaction } from './types';
+import { artifacts } from '../../src/artifacts';
export class ExchangeWrapper {
private readonly _exchange: ExchangeContract;
@@ -17,7 +21,7 @@ export class ExchangeWrapper {
constructor(exchangeContract: ExchangeContract, provider: Provider) {
this._exchange = exchangeContract;
this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper);
+ this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
}
public async fillOrderAsync(
signedOrder: SignedOrder,
diff --git a/contracts/core/test/utils/fill_order_combinatorial_utils.ts b/contracts/core/test/utils/fill_order_combinatorial_utils.ts
index 8046771f9..6372ad29a 100644
--- a/contracts/core/test/utils/fill_order_combinatorial_utils.ts
+++ b/contracts/core/test/utils/fill_order_combinatorial_utils.ts
@@ -1,4 +1,21 @@
import {
+ AllowanceAmountScenario,
+ AssetDataScenario,
+ BalanceAmountScenario,
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ ExpirationTimeSecondsScenario,
+ FeeRecipientAddressScenario,
+ FillScenario,
+ OrderAssetAmountScenario,
+ orderUtils,
+ signingUtils,
+ TakerAssetFillAmountScenario,
+ TakerScenario,
+ TraderStateScenario,
+} from '@0x/contracts-test-utils';
+import {
assetDataUtils,
BalanceAndProxyAllowanceLazyStore,
ExchangeTransferSimulator,
@@ -18,30 +35,13 @@ import { ExchangeContract, ExchangeFillEventArgs } from '../../generated-wrapper
import { TestLibsContract } from '../../generated-wrappers/test_libs';
import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync } from './assertions';
import { AssetWrapper } from './asset_wrapper';
-import { chaiSetup } from './chai_setup';
-import { constants } from './constants';
import { ERC20Wrapper } from './erc20_wrapper';
import { ERC721Wrapper } from './erc721_wrapper';
import { ExchangeWrapper } from './exchange_wrapper';
import { OrderFactoryFromScenario } from './order_factory_from_scenario';
-import { orderUtils } from './order_utils';
-import { signingUtils } from './signing_utils';
import { SimpleAssetBalanceAndProxyAllowanceFetcher } from './simple_asset_balance_and_proxy_allowance_fetcher';
import { SimpleOrderFilledCancelledFetcher } from './simple_order_filled_cancelled_fetcher';
-import {
- AllowanceAmountScenario,
- AssetDataScenario,
- BalanceAmountScenario,
- ExpirationTimeSecondsScenario,
- FeeRecipientAddressScenario,
- FillScenario,
- OrderAssetAmountScenario,
- TakerAssetFillAmountScenario,
- TakerScenario,
- TraderStateScenario,
-} from './types';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/core/test/utils/forwarder_wrapper.ts b/contracts/core/test/utils/forwarder_wrapper.ts
index a0bfcfe1d..9c5560381 100644
--- a/contracts/core/test/utils/forwarder_wrapper.ts
+++ b/contracts/core/test/utils/forwarder_wrapper.ts
@@ -1,3 +1,4 @@
+import { constants, formatters, LogDecoder, MarketSellOrders } from '@0x/contracts-test-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@@ -5,11 +6,7 @@ import { Provider, TransactionReceiptWithDecodedLogs, TxDataPayable } from 'ethe
import * as _ from 'lodash';
import { ForwarderContract } from '../../generated-wrappers/forwarder';
-
-import { constants } from './constants';
-import { formatters } from './formatters';
-import { LogDecoder } from './log_decoder';
-import { MarketSellOrders } from './types';
+import { artifacts } from '../../src/artifacts';
export class ForwarderWrapper {
private readonly _web3Wrapper: Web3Wrapper;
@@ -61,7 +58,7 @@ export class ForwarderWrapper {
constructor(contractInstance: ForwarderContract, provider: Provider) {
this._forwarderContract = contractInstance;
this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper);
+ this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
}
public async marketSellOrdersWithEthAsync(
orders: SignedOrder[],
diff --git a/contracts/core/test/utils/match_order_tester.ts b/contracts/core/test/utils/match_order_tester.ts
index 6c2c84959..8f574704e 100644
--- a/contracts/core/test/utils/match_order_tester.ts
+++ b/contracts/core/test/utils/match_order_tester.ts
@@ -1,3 +1,12 @@
+import {
+ chaiSetup,
+ ERC20BalancesByOwner,
+ ERC721TokenIdsByOwner,
+ OrderInfo,
+ OrderStatus,
+ TransferAmountsByMatchOrders as TransferAmounts,
+ TransferAmountsLoggedByMatchOrders as LoggedTransferAmounts,
+} from '@0x/contracts-test-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { AssetProxyId, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -6,18 +15,9 @@ import * as _ from 'lodash';
import { TransactionReceiptWithDecodedLogs } from '../../../../node_modules/ethereum-types';
-import { chaiSetup } from './chai_setup';
import { ERC20Wrapper } from './erc20_wrapper';
import { ERC721Wrapper } from './erc721_wrapper';
import { ExchangeWrapper } from './exchange_wrapper';
-import {
- ERC20BalancesByOwner,
- ERC721TokenIdsByOwner,
- OrderInfo,
- OrderStatus,
- TransferAmountsByMatchOrders as TransferAmounts,
- TransferAmountsLoggedByMatchOrders as LoggedTransferAmounts,
-} from './types';
chaiSetup.configure();
const expect = chai.expect;
@@ -270,18 +270,14 @@ export class MatchOrderTester {
const leftExpectedStatus = expectedTransferAmounts.amountBoughtByLeftMaker.equals(maxAmountBoughtByLeftMaker)
? OrderStatus.FULLY_FILLED
: OrderStatus.FILLABLE;
- expect(leftOrderInfo.orderStatus as OrderStatus, 'Checking exchange status for left order').to.be.equal(
- leftExpectedStatus,
- );
+ expect(leftOrderInfo.orderStatus, 'Checking exchange status for left order').to.be.equal(leftExpectedStatus);
// Assert right order status
const maxAmountBoughtByRightMaker = signedOrderRight.takerAssetAmount.minus(initialRightOrderFilledAmount);
const rightOrderInfo: OrderInfo = await this._exchangeWrapper.getOrderInfoAsync(signedOrderRight);
const rightExpectedStatus = expectedTransferAmounts.amountBoughtByRightMaker.equals(maxAmountBoughtByRightMaker)
? OrderStatus.FULLY_FILLED
: OrderStatus.FILLABLE;
- expect(rightOrderInfo.orderStatus as OrderStatus, 'Checking exchange status for right order').to.be.equal(
- rightExpectedStatus,
- );
+ expect(rightOrderInfo.orderStatus, 'Checking exchange status for right order').to.be.equal(rightExpectedStatus);
}
/// @dev Asserts account balances after matching orders.
/// @param signedOrderLeft First matched order.
diff --git a/contracts/core/test/utils/order_factory_from_scenario.ts b/contracts/core/test/utils/order_factory_from_scenario.ts
index 60c8606c4..1cc962020 100644
--- a/contracts/core/test/utils/order_factory_from_scenario.ts
+++ b/contracts/core/test/utils/order_factory_from_scenario.ts
@@ -1,19 +1,18 @@
-import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
-import { Order } from '@0x/types';
-import { BigNumber, errorUtils } from '@0x/utils';
-
-import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_token';
-
-import { constants } from './constants';
import {
AssetDataScenario,
+ constants,
ERC721TokenIdsByOwner,
ExpirationTimeSecondsScenario,
FeeRecipientAddressScenario,
OrderAssetAmountScenario,
OrderScenario,
TakerScenario,
-} from './types';
+} from '@0x/contracts-test-utils';
+import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
+import { Order } from '@0x/types';
+import { BigNumber, errorUtils } from '@0x/utils';
+
+import { DummyERC721TokenContract } from '../../generated-wrappers/dummy_erc721_token';
const TEN_UNITS_EIGHTEEN_DECIMALS = new BigNumber(10_000_000_000_000_000_000);
const FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(5_000_000_000_000_000_000);
diff --git a/contracts/core/tsconfig.json b/contracts/core/tsconfig.json
index e0f85079a..82d37b51e 100644
--- a/contracts/core/tsconfig.json
+++ b/contracts/core/tsconfig.json
@@ -13,6 +13,7 @@
"./generated-artifacts/DummyERC721Token.json",
"./generated-artifacts/DummyMultipleReturnERC20Token.json",
"./generated-artifacts/DummyNoReturnERC20Token.json",
+ "./generated-artifacts/DutchAuction.json",
"./generated-artifacts/ERC20Proxy.json",
"./generated-artifacts/ERC20Token.json",
"./generated-artifacts/ERC721Proxy.json",
@@ -27,15 +28,11 @@
"./generated-artifacts/InvalidERC721Receiver.json",
"./generated-artifacts/MixinAuthorizable.json",
"./generated-artifacts/MultiAssetProxy.json",
- "./generated-artifacts/MultiSigWallet.json",
- "./generated-artifacts/MultiSigWalletWithTimeLock.json",
"./generated-artifacts/OrderValidator.json",
"./generated-artifacts/ReentrantERC20Token.json",
"./generated-artifacts/TestAssetProxyDispatcher.json",
"./generated-artifacts/TestAssetProxyOwner.json",
- "./generated-artifacts/TestConstants.json",
"./generated-artifacts/TestExchangeInternals.json",
- "./generated-artifacts/TestLibBytes.json",
"./generated-artifacts/TestLibs.json",
"./generated-artifacts/TestSignatureValidator.json",
"./generated-artifacts/TestStaticCallReceiver.json",
diff --git a/contracts/multisig/.solhint.json b/contracts/multisig/.solhint.json
new file mode 100644
index 000000000..076afe9f3
--- /dev/null
+++ b/contracts/multisig/.solhint.json
@@ -0,0 +1,20 @@
+{
+ "extends": "default",
+ "rules": {
+ "avoid-low-level-calls": false,
+ "avoid-tx-origin": "warn",
+ "bracket-align": false,
+ "code-complexity": false,
+ "const-name-snakecase": "error",
+ "expression-indent": "error",
+ "function-max-lines": false,
+ "func-order": "error",
+ "indent": ["error", 4],
+ "max-line-length": ["warn", 160],
+ "no-inline-assembly": false,
+ "quotes": ["error", "double"],
+ "separate-by-one-line-in-contract": "error",
+ "space-after-comma": "error",
+ "statement-indent": "error"
+ }
+}
diff --git a/contracts/multisig/CHANGELOG.json b/contracts/multisig/CHANGELOG.json
new file mode 100644
index 000000000..fe51488c7
--- /dev/null
+++ b/contracts/multisig/CHANGELOG.json
@@ -0,0 +1 @@
+[]
diff --git a/contracts/multisig/README.md b/contracts/multisig/README.md
new file mode 100644
index 000000000..93db63b5b
--- /dev/null
+++ b/contracts/multisig/README.md
@@ -0,0 +1,70 @@
+## MultisSig Contracts
+
+MultiSig smart contracts
+
+## Usage
+
+Contracts can be found in the [contracts](./contracts) directory. The contents of this directory are broken down into the following subdirectories:
+
+* [multisig](./contracts/multisig)
+ * This directory contains the [Gnosis MultiSigWallet](https://github.com/gnosis/MultiSigWallet) and a custom extension that adds a timelock to transactions within the MultiSigWallet.
+* [test](./contracts/test)
+ * This directory contains mocks and other contracts that are used solely for testing contracts within the other directories.
+
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
+
+For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
+
+### Install Dependencies
+
+If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
+
+```bash
+yarn config set workspaces-experimental true
+```
+
+Then install dependencies
+
+```bash
+yarn install
+```
+
+### Build
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=@0x/contracts-multisig yarn build
+```
+
+Or continuously rebuild on change:
+
+```bash
+PKG=@0x/contracts-multisig yarn watch
+```
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
+
+### Run Tests
+
+```bash
+yarn test
+```
+
+#### Testing options
+
+Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
diff --git a/contracts/multisig/compiler.json b/contracts/multisig/compiler.json
new file mode 100644
index 000000000..5a1f689e2
--- /dev/null
+++ b/contracts/multisig/compiler.json
@@ -0,0 +1,22 @@
+{
+ "artifactsDir": "./generated-artifacts",
+ "contractsDir": "./contracts",
+ "compilerSettings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode.object",
+ "evm.bytecode.sourceMap",
+ "evm.deployedBytecode.object",
+ "evm.deployedBytecode.sourceMap"
+ ]
+ }
+ }
+ },
+ "contracts": ["MultiSigWallet", "MultiSigWalletWithTimeLock", "TestRejectEther"]
+}
diff --git a/contracts/core/contracts/multisig/MultiSigWallet.sol b/contracts/multisig/contracts/multisig/MultiSigWallet.sol
index 516e7391c..516e7391c 100644
--- a/contracts/core/contracts/multisig/MultiSigWallet.sol
+++ b/contracts/multisig/contracts/multisig/MultiSigWallet.sol
diff --git a/contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol b/contracts/multisig/contracts/multisig/MultiSigWalletWithTimeLock.sol
index 9513d3b30..9513d3b30 100644
--- a/contracts/core/contracts/multisig/MultiSigWalletWithTimeLock.sol
+++ b/contracts/multisig/contracts/multisig/MultiSigWalletWithTimeLock.sol
diff --git a/contracts/multisig/contracts/test/TestRejectEther/TestRejectEther.sol b/contracts/multisig/contracts/test/TestRejectEther/TestRejectEther.sol
new file mode 100644
index 000000000..e523f591d
--- /dev/null
+++ b/contracts/multisig/contracts/test/TestRejectEther/TestRejectEther.sol
@@ -0,0 +1,23 @@
+/*
+
+ Copyright 2018 ZeroEx Intl.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+pragma solidity 0.4.24;
+
+
+// solhint-disable no-empty-blocks
+contract TestRejectEther {}
diff --git a/contracts/multisig/package.json b/contracts/multisig/package.json
new file mode 100644
index 000000000..37d064fef
--- /dev/null
+++ b/contracts/multisig/package.json
@@ -0,0 +1,86 @@
+{
+ "private": true,
+ "name": "@0x/contracts-multisig",
+ "version": "1.0.0",
+ "engines": {
+ "node": ">=6.12"
+ },
+ "description": "Multisig contracts used by 0x protocol",
+ "main": "lib/src/index.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "build": "yarn pre_build && tsc -b",
+ "build:ci": "yarn build",
+ "pre_build": "run-s compile generate_contract_wrappers",
+ "test": "yarn run_mocha",
+ "rebuild_and_test": "run-s build test",
+ "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
+ "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
+ "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
+ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
+ "compile": "sol-compiler --contracts-dir contracts",
+ "clean": "shx rm -rf lib generated-artifacts generated-wrappers",
+ "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../packages/abi-gen-templates/contract.handlebars --partials '../../packages/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
+ "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
+ "coverage:report:text": "istanbul report text",
+ "coverage:report:html": "istanbul report html && open coverage/index.html",
+ "profiler:report:html": "istanbul report html && open coverage/index.html",
+ "coverage:report:lcov": "istanbul report lcov",
+ "test:circleci": "yarn test",
+ "lint-contracts": "solhint contracts/**/**/**/**/*.sol"
+ },
+ "config": {
+ "abis": "generated-artifacts/@(MultiSigWallet|MultiSigWalletWithTimeLock|TestRejectEther).json"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/0xProject/0x-monorepo.git"
+ },
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/0xProject/0x-monorepo/issues"
+ },
+ "homepage": "https://github.com/0xProject/0x-monorepo/contracts/core/README.md",
+ "devDependencies": {
+ "@0x/contracts-test-utils": "^1.0.0",
+ "@0x/abi-gen": "^1.0.17",
+ "@0x/dev-utils": "^1.0.18",
+ "@0x/sol-compiler": "^1.1.13",
+ "@0x/sol-cov": "^2.1.13",
+ "@0x/subproviders": "^2.1.5",
+ "@0x/tslint-config": "^1.0.10",
+ "@types/bn.js": "^4.11.0",
+ "@types/ethereumjs-abi": "^0.6.0",
+ "@types/lodash": "4.14.104",
+ "@types/node": "*",
+ "@types/yargs": "^10.0.0",
+ "chai": "^4.0.1",
+ "chai-as-promised": "^7.1.0",
+ "chai-bignumber": "^2.0.1",
+ "dirty-chai": "^2.0.1",
+ "make-promises-safe": "^1.1.0",
+ "mocha": "^4.1.0",
+ "npm-run-all": "^4.1.2",
+ "shx": "^0.2.2",
+ "solc": "^0.4.24",
+ "solhint": "^1.2.1",
+ "tslint": "5.11.0",
+ "typescript": "3.0.1",
+ "yargs": "^10.0.3"
+ },
+ "dependencies": {
+ "@0x/base-contract": "^3.0.7",
+ "@0x/order-utils": "^3.0.3",
+ "@0x/types": "^1.3.0",
+ "@0x/typescript-typings": "^3.0.4",
+ "@0x/utils": "^2.0.6",
+ "@0x/web3-wrapper": "^3.1.5",
+ "ethereum-types": "^1.1.2",
+ "lodash": "^4.17.5"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/contracts/multisig/src/artifacts/index.ts b/contracts/multisig/src/artifacts/index.ts
new file mode 100644
index 000000000..7cf47be01
--- /dev/null
+++ b/contracts/multisig/src/artifacts/index.ts
@@ -0,0 +1,11 @@
+import { ContractArtifact } from 'ethereum-types';
+
+import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
+import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
+import * as TestRejectEther from '../../generated-artifacts/TestRejectEther.json';
+
+export const artifacts = {
+ TestRejectEther: TestRejectEther as ContractArtifact,
+ MultiSigWallet: MultiSigWallet as ContractArtifact,
+ MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
+};
diff --git a/contracts/multisig/src/wrappers/index.ts b/contracts/multisig/src/wrappers/index.ts
new file mode 100644
index 000000000..69abd62f2
--- /dev/null
+++ b/contracts/multisig/src/wrappers/index.ts
@@ -0,0 +1,2 @@
+export * from '../../generated-wrappers/multi_sig_wallet';
+export * from '../../generated-wrappers/multi_sig_wallet_with_time_lock';
diff --git a/contracts/multisig/test/global_hooks.ts b/contracts/multisig/test/global_hooks.ts
new file mode 100644
index 000000000..68eb4f8d5
--- /dev/null
+++ b/contracts/multisig/test/global_hooks.ts
@@ -0,0 +1,19 @@
+import { env, EnvVars } from '@0x/dev-utils';
+
+import { coverage, profiler, provider } from '@0x/contracts-test-utils';
+
+before('start web3 provider engine', () => {
+ provider.start();
+});
+
+after('generate coverage report', async () => {
+ if (env.parseBoolean(EnvVars.SolidityCoverage)) {
+ const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
+ await coverageSubprovider.writeCoverageAsync();
+ }
+ if (env.parseBoolean(EnvVars.SolidityProfiler)) {
+ const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
+ await profilerSubprovider.writeProfilerOutputAsync();
+ }
+ provider.stop();
+});
diff --git a/contracts/core/test/multisig/multi_sig_with_time_lock.ts b/contracts/multisig/test/multi_sig_with_time_lock.ts
index 1c0cb0515..31c215505 100644
--- a/contracts/core/test/multisig/multi_sig_with_time_lock.ts
+++ b/contracts/multisig/test/multi_sig_with_time_lock.ts
@@ -1,3 +1,13 @@
+import {
+ chaiSetup,
+ constants,
+ expectTransactionFailedAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ increaseTimeAndMineBlockAsync,
+ provider,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -5,7 +15,6 @@ import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
-import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
import {
MultiSigWalletWithTimeLockConfirmationEventArgs,
MultiSigWalletWithTimeLockConfirmationTimeSetEventArgs,
@@ -13,14 +22,11 @@ import {
MultiSigWalletWithTimeLockExecutionEventArgs,
MultiSigWalletWithTimeLockExecutionFailureEventArgs,
MultiSigWalletWithTimeLockSubmissionEventArgs,
-} from '../../generated-wrappers/multi_sig_wallet_with_time_lock';
-import { artifacts } from '../../src/artifacts';
-import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
-import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { MultiSigWrapper } from '../utils/multi_sig_wrapper';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
+} from '../generated-wrappers/multi_sig_wallet_with_time_lock';
+import { TestRejectEtherContract } from '../generated-wrappers/test_reject_ether';
+import { artifacts } from '../src/artifacts';
+
+import { MultiSigWrapper } from './utils/multi_sig_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -189,14 +195,10 @@ describe('MultiSigWalletWithTimeLock', () => {
await expectTransactionFailedWithoutReasonAsync(multiSigWrapper.executeTransactionAsync(txId, owners[1]));
});
it("should log an ExecutionFailure event and not update the transaction's execution state if unsuccessful", async () => {
- const contractWithoutFallback = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
- artifacts.DummyERC20Token,
+ const contractWithoutFallback = await TestRejectEtherContract.deployFrom0xArtifactAsync(
+ artifacts.TestRejectEther,
provider,
txDefaults,
- constants.DUMMY_TOKEN_NAME,
- constants.DUMMY_TOKEN_SYMBOL,
- constants.DUMMY_TOKEN_DECIMALS,
- constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
const data = constants.NULL_BYTES;
const value = new BigNumber(10);
diff --git a/contracts/core/test/utils/multi_sig_wrapper.ts b/contracts/multisig/test/utils/multi_sig_wrapper.ts
index 74fd3b4d6..086143613 100644
--- a/contracts/core/test/utils/multi_sig_wrapper.ts
+++ b/contracts/multisig/test/utils/multi_sig_wrapper.ts
@@ -1,12 +1,11 @@
+import { LogDecoder } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
-import { AssetProxyOwnerContract } from '../../generated-wrappers/asset_proxy_owner';
import { MultiSigWalletContract } from '../../generated-wrappers/multi_sig_wallet';
-
-import { LogDecoder } from './log_decoder';
+import { artifacts } from '../../src/artifacts';
export class MultiSigWrapper {
private readonly _multiSig: MultiSigWalletContract;
@@ -15,7 +14,7 @@ export class MultiSigWrapper {
constructor(multiSigContract: MultiSigWalletContract, provider: Provider) {
this._multiSig = multiSigContract;
this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper);
+ this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
}
public async submitTransactionAsync(
destination: string,
@@ -52,16 +51,4 @@ export class MultiSigWrapper {
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
- public async executeRemoveAuthorizedAddressAtIndexAsync(
- txId: BigNumber,
- from: string,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const txHash = await (this
- ._multiSig as AssetProxyOwnerContract).executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, {
- from,
- });
- const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return tx;
- }
}
diff --git a/contracts/multisig/tsconfig.json b/contracts/multisig/tsconfig.json
new file mode 100644
index 000000000..6f381620e
--- /dev/null
+++ b/contracts/multisig/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "outDir": "lib",
+ "rootDir": ".",
+ "resolveJsonModule": true
+ },
+ "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
+ "files": [
+ "./generated-artifacts/MultiSigWallet.json",
+ "./generated-artifacts/MultiSigWalletWithTimeLock.json",
+ "./generated-artifacts/TestRejectEther.json"
+ ],
+ "exclude": ["./deploy/solc/solc_bin"]
+}
diff --git a/contracts/multisig/tslint.json b/contracts/multisig/tslint.json
new file mode 100644
index 000000000..1bb3ac2a2
--- /dev/null
+++ b/contracts/multisig/tslint.json
@@ -0,0 +1,6 @@
+{
+ "extends": ["@0x/tslint-config"],
+ "rules": {
+ "custom-no-magic-numbers": false
+ }
+}
diff --git a/contracts/test-utils/README.md b/contracts/test-utils/README.md
new file mode 100644
index 000000000..73fd93f45
--- /dev/null
+++ b/contracts/test-utils/README.md
@@ -0,0 +1,73 @@
+## Contracts test utils
+
+This package contains test utilities used by other smart contracts packages.
+
+## Usage
+
+```typescript
+import {
+ chaiSetup,
+ constants,
+ expectContractCallFailedAsync,
+ expectContractCreationFailedAsync,
+ expectTransactionFailedAsync,
+ expectTransactionFailedWithoutReasonAsync,
+ increaseTimeAndMineBlockAsync,
+ provider,
+ sendTransactionResult,
+ txDefaults,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
+```
+
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
+
+### Install Dependencies
+
+If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
+
+```bash
+yarn config set workspaces-experimental true
+```
+
+Then install dependencies
+
+```bash
+yarn install
+```
+
+### Build
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=@0x/contracts-test-utils yarn build
+```
+
+Or continuously rebuild on change:
+
+```bash
+PKG=@0x/contracts-test-utils yarn watch
+```
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
+
+### Run Tests
+
+```bash
+yarn test
+```
diff --git a/contracts/test-utils/package.json b/contracts/test-utils/package.json
new file mode 100644
index 000000000..513cfdc10
--- /dev/null
+++ b/contracts/test-utils/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "@0x/contracts-test-utils",
+ "version": "1.0.0",
+ "engines": {
+ "node": ">=6.12"
+ },
+ "description": "Test utils for 0x contracts",
+ "main": "lib/src/index.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "build": "tsc -b",
+ "build:ci": "yarn build",
+ "test": "yarn run_mocha",
+ "test:coverage": "run-s build run_mocha coverage:report:text coverage:report:lcov",
+ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
+ "clean": "shx rm -rf lib",
+ "lint": "tslint --format stylish --project tsconfig.lint.json",
+ "coverage:report:text": "istanbul report text",
+ "coverage:report:html": "istanbul report html && open coverage/index.html",
+ "profiler:report:html": "istanbul report html && open coverage/index.html",
+ "coverage:report:lcov": "istanbul report lcov",
+ "test:circleci": "yarn test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/0xProject/0x-monorepo.git"
+ },
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/0xProject/0x-monorepo/issues"
+ },
+ "homepage": "https://github.com/0xProject/0x-monorepo/contracts/test-utils/README.md",
+ "devDependencies": {
+ "mocha": "^4.1.0",
+ "npm-run-all": "^4.1.2",
+ "shx": "^0.2.2",
+ "tslint": "5.11.0",
+ "typescript": "3.0.1"
+ },
+ "dependencies": {
+ "@0x/abi-gen": "^1.0.17",
+ "@0x/dev-utils": "^1.0.18",
+ "@0x/sol-compiler": "^1.1.13",
+ "@0x/subproviders": "^2.1.5",
+ "@0x/tslint-config": "^1.0.10",
+ "@types/bn.js": "^4.11.0",
+ "@types/ethereumjs-abi": "^0.6.0",
+ "@types/lodash": "4.14.104",
+ "@types/node": "*",
+ "chai": "^4.0.1",
+ "chai-bignumber": "^2.0.1",
+ "dirty-chai": "^2.0.1",
+ "make-promises-safe": "^1.1.0",
+ "@0x/order-utils": "^3.0.3",
+ "@0x/types": "^1.3.0",
+ "@0x/typescript-typings": "^3.0.4",
+ "@0x/utils": "^2.0.6",
+ "@0x/sol-cov": "^2.1.13",
+ "@0x/web3-wrapper": "^3.1.5",
+ "@types/js-combinatorics": "^0.5.29",
+ "chai-as-promised": "^7.1.0",
+ "bn.js": "^4.11.8",
+ "ethereum-types": "^1.1.2",
+ "ethereumjs-abi": "0.6.5",
+ "ethereumjs-util": "^5.1.1",
+ "ethers": "~4.0.4",
+ "js-combinatorics": "^0.5.3",
+ "lodash": "^4.17.5"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/contracts/core/test/utils/abstract_asset_wrapper.ts b/contracts/test-utils/src/abstract_asset_wrapper.ts
index 4b56a8502..4b56a8502 100644
--- a/contracts/core/test/utils/abstract_asset_wrapper.ts
+++ b/contracts/test-utils/src/abstract_asset_wrapper.ts
diff --git a/contracts/core/test/utils/address_utils.ts b/contracts/test-utils/src/address_utils.ts
index 634da0c16..634da0c16 100644
--- a/contracts/core/test/utils/address_utils.ts
+++ b/contracts/test-utils/src/address_utils.ts
diff --git a/contracts/core/test/utils/assertions.ts b/contracts/test-utils/src/assertions.ts
index 5b1cedfcc..5b1cedfcc 100644
--- a/contracts/core/test/utils/assertions.ts
+++ b/contracts/test-utils/src/assertions.ts
diff --git a/contracts/core/test/utils/block_timestamp.ts b/contracts/test-utils/src/block_timestamp.ts
index 66c13eed1..66c13eed1 100644
--- a/contracts/core/test/utils/block_timestamp.ts
+++ b/contracts/test-utils/src/block_timestamp.ts
diff --git a/contracts/core/test/utils/chai_setup.ts b/contracts/test-utils/src/chai_setup.ts
index 1a8733093..1a8733093 100644
--- a/contracts/core/test/utils/chai_setup.ts
+++ b/contracts/test-utils/src/chai_setup.ts
diff --git a/contracts/core/test/utils/combinatorial_utils.ts b/contracts/test-utils/src/combinatorial_utils.ts
index bb1b55b4d..bb1b55b4d 100644
--- a/contracts/core/test/utils/combinatorial_utils.ts
+++ b/contracts/test-utils/src/combinatorial_utils.ts
diff --git a/contracts/core/test/utils/constants.ts b/contracts/test-utils/src/constants.ts
index d2c3ab512..d2c3ab512 100644
--- a/contracts/core/test/utils/constants.ts
+++ b/contracts/test-utils/src/constants.ts
diff --git a/contracts/core/test/utils/coverage.ts b/contracts/test-utils/src/coverage.ts
index 5becfa1b6..5becfa1b6 100644
--- a/contracts/core/test/utils/coverage.ts
+++ b/contracts/test-utils/src/coverage.ts
diff --git a/contracts/core/test/utils/formatters.ts b/contracts/test-utils/src/formatters.ts
index 813eb45db..813eb45db 100644
--- a/contracts/core/test/utils/formatters.ts
+++ b/contracts/test-utils/src/formatters.ts
diff --git a/contracts/test-utils/src/global_hooks.ts b/contracts/test-utils/src/global_hooks.ts
new file mode 100644
index 000000000..307dd0777
--- /dev/null
+++ b/contracts/test-utils/src/global_hooks.ts
@@ -0,0 +1,15 @@
+import { env, EnvVars } from '@0x/dev-utils';
+
+import { coverage } from './coverage';
+import { profiler } from './profiler';
+
+after('generate coverage report', async () => {
+ if (env.parseBoolean(EnvVars.SolidityCoverage)) {
+ const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
+ await coverageSubprovider.writeCoverageAsync();
+ }
+ if (env.parseBoolean(EnvVars.SolidityProfiler)) {
+ const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
+ await profilerSubprovider.writeProfilerOutputAsync();
+ }
+});
diff --git a/contracts/test-utils/src/index.ts b/contracts/test-utils/src/index.ts
new file mode 100644
index 000000000..7880de0bf
--- /dev/null
+++ b/contracts/test-utils/src/index.ts
@@ -0,0 +1,55 @@
+export { AbstractAssetWrapper } from './abstract_asset_wrapper';
+export { chaiSetup } from './chai_setup';
+export { constants } from './constants';
+export {
+ expectContractCallFailedAsync,
+ expectContractCallFailedWithoutReasonAsync,
+ expectContractCreationFailedAsync,
+ expectContractCreationFailedWithoutReasonAsync,
+ expectInsufficientFundsAsync,
+ expectTransactionFailedAsync,
+ sendTransactionResult,
+ expectTransactionFailedWithoutReasonAsync,
+ getInvalidOpcodeErrorMessageForCallAsync,
+ getRevertReasonOrErrorMessageForSendTransactionAsync,
+} from './assertions';
+export { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from './block_timestamp';
+export { provider, txDefaults, web3Wrapper } from './web3_wrapper';
+export { LogDecoder } from './log_decoder';
+export { formatters } from './formatters';
+export { signingUtils } from './signing_utils';
+export { orderUtils } from './order_utils';
+export { typeEncodingUtils } from './type_encoding_utils';
+export { profiler } from './profiler';
+export { coverage } from './coverage';
+export { addressUtils } from './address_utils';
+export { OrderFactory } from './order_factory';
+export { bytes32Values, testCombinatoriallyWithReferenceFuncAsync, uint256Values } from './combinatorial_utils';
+export { TransactionFactory } from './transaction_factory';
+export { testWithReferenceFuncAsync } from './test_with_reference';
+export {
+ MarketBuyOrders,
+ MarketSellOrders,
+ ERC721TokenIdsByOwner,
+ SignedTransaction,
+ OrderStatus,
+ AllowanceAmountScenario,
+ AssetDataScenario,
+ BalanceAmountScenario,
+ ContractName,
+ ExpirationTimeSecondsScenario,
+ TransferAmountsLoggedByMatchOrders,
+ TransferAmountsByMatchOrders,
+ OrderScenario,
+ TraderStateScenario,
+ TransactionDataParams,
+ Token,
+ FillScenario,
+ FeeRecipientAddressScenario,
+ OrderAssetAmountScenario,
+ TakerAssetFillAmountScenario,
+ TakerScenario,
+ OrderInfo,
+ ERC20BalancesByOwner,
+ FillResults,
+} from './types';
diff --git a/contracts/core/test/utils/log_decoder.ts b/contracts/test-utils/src/log_decoder.ts
index 05b0a9204..54666ea5f 100644
--- a/contracts/core/test/utils/log_decoder.ts
+++ b/contracts/test-utils/src/log_decoder.ts
@@ -11,8 +11,6 @@ import {
} from 'ethereum-types';
import * as _ from 'lodash';
-import { artifacts } from '../../src/artifacts';
-
import { constants } from './constants';
export class LogDecoder {
@@ -27,7 +25,7 @@ export class LogDecoder {
}
}
}
- constructor(web3Wrapper: Web3Wrapper) {
+ constructor(web3Wrapper: Web3Wrapper, artifacts: { [contractName: string]: ContractArtifact }) {
this._web3Wrapper = web3Wrapper;
const abiArrays: AbiDefinition[][] = [];
_.forEach(artifacts, (artifact: ContractArtifact) => {
diff --git a/contracts/core/test/utils/order_factory.ts b/contracts/test-utils/src/order_factory.ts
index 2449d1a8a..2449d1a8a 100644
--- a/contracts/core/test/utils/order_factory.ts
+++ b/contracts/test-utils/src/order_factory.ts
diff --git a/contracts/core/test/utils/order_utils.ts b/contracts/test-utils/src/order_utils.ts
index 4f7a34011..4f7a34011 100644
--- a/contracts/core/test/utils/order_utils.ts
+++ b/contracts/test-utils/src/order_utils.ts
diff --git a/contracts/core/test/utils/profiler.ts b/contracts/test-utils/src/profiler.ts
index 2c7c1d66c..2c7c1d66c 100644
--- a/contracts/core/test/utils/profiler.ts
+++ b/contracts/test-utils/src/profiler.ts
diff --git a/contracts/core/test/utils/revert_trace.ts b/contracts/test-utils/src/revert_trace.ts
index 3f74fd28b..3f74fd28b 100644
--- a/contracts/core/test/utils/revert_trace.ts
+++ b/contracts/test-utils/src/revert_trace.ts
diff --git a/contracts/core/test/utils/signing_utils.ts b/contracts/test-utils/src/signing_utils.ts
index 21f864bfa..21f864bfa 100644
--- a/contracts/core/test/utils/signing_utils.ts
+++ b/contracts/test-utils/src/signing_utils.ts
diff --git a/contracts/core/test/utils/test_with_reference.ts b/contracts/test-utils/src/test_with_reference.ts
index b80be4a6c..b80be4a6c 100644
--- a/contracts/core/test/utils/test_with_reference.ts
+++ b/contracts/test-utils/src/test_with_reference.ts
diff --git a/contracts/core/test/utils/transaction_factory.ts b/contracts/test-utils/src/transaction_factory.ts
index dbab3ade4..dbab3ade4 100644
--- a/contracts/core/test/utils/transaction_factory.ts
+++ b/contracts/test-utils/src/transaction_factory.ts
diff --git a/contracts/core/test/utils/type_encoding_utils.ts b/contracts/test-utils/src/type_encoding_utils.ts
index bfd9c9ef5..bfd9c9ef5 100644
--- a/contracts/core/test/utils/type_encoding_utils.ts
+++ b/contracts/test-utils/src/type_encoding_utils.ts
diff --git a/contracts/core/test/utils/types.ts b/contracts/test-utils/src/types.ts
index 9fc9e1570..d738fcd4e 100644
--- a/contracts/core/test/utils/types.ts
+++ b/contracts/test-utils/src/types.ts
@@ -86,6 +86,7 @@ export enum ContractName {
ZRXToken = 'ZRXToken',
DummyERC20Token = 'DummyERC20Token',
EtherToken = 'WETH9',
+ DutchAuction = 'DutchAuction',
AssetProxyOwner = 'AssetProxyOwner',
AccountLevels = 'AccountLevels',
EtherDelta = 'EtherDelta',
diff --git a/contracts/core/test/utils/web3_wrapper.ts b/contracts/test-utils/src/web3_wrapper.ts
index f7b1a732a..cb33476f3 100644
--- a/contracts/core/test/utils/web3_wrapper.ts
+++ b/contracts/test-utils/src/web3_wrapper.ts
@@ -48,6 +48,7 @@ const ganacheConfigs = {
const providerConfigs = testProvider === ProviderType.Ganache ? ganacheConfigs : gethConfigs;
export const provider: Web3ProviderEngine = web3Factory.getRpcProvider(providerConfigs);
+provider.stop();
const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage);
const isProfilerEnabled = env.parseBoolean(EnvVars.SolidityProfiler);
const isRevertTraceEnabled = env.parseBoolean(EnvVars.SolidityRevertTrace);
diff --git a/contracts/core/test/utils_test/test_with_reference.ts b/contracts/test-utils/test/test_with_reference.ts
index 8d633cd1f..1c1211003 100644
--- a/contracts/core/test/utils_test/test_with_reference.ts
+++ b/contracts/test-utils/test/test_with_reference.ts
@@ -1,7 +1,7 @@
import * as chai from 'chai';
-import { chaiSetup } from '../utils/chai_setup';
-import { testWithReferenceFuncAsync } from '../utils/test_with_reference';
+import { chaiSetup } from '../src/chai_setup';
+import { testWithReferenceFuncAsync } from '../src/test_with_reference';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/test-utils/tsconfig.json b/contracts/test-utils/tsconfig.json
new file mode 100644
index 000000000..e35816553
--- /dev/null
+++ b/contracts/test-utils/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "outDir": "lib"
+ },
+ "include": ["./src/**/*", "./test/**/*"]
+}
diff --git a/contracts/test-utils/tsconfig.lint.json b/contracts/test-utils/tsconfig.lint.json
new file mode 100644
index 000000000..b557e706a
--- /dev/null
+++ b/contracts/test-utils/tsconfig.lint.json
@@ -0,0 +1,7 @@
+{
+ // This file is a workaround that issue: https://github.com/palantir/tslint/issues/4148#issuecomment-419872702
+ "extends": "./tsconfig",
+ "compilerOptions": {
+ "composite": false
+ }
+}
diff --git a/contracts/test-utils/tslint.json b/contracts/test-utils/tslint.json
new file mode 100644
index 000000000..1bb3ac2a2
--- /dev/null
+++ b/contracts/test-utils/tslint.json
@@ -0,0 +1,6 @@
+{
+ "extends": ["@0x/tslint-config"],
+ "rules": {
+ "custom-no-magic-numbers": false
+ }
+}
diff --git a/contracts/utils/.solhint.json b/contracts/utils/.solhint.json
new file mode 100644
index 000000000..076afe9f3
--- /dev/null
+++ b/contracts/utils/.solhint.json
@@ -0,0 +1,20 @@
+{
+ "extends": "default",
+ "rules": {
+ "avoid-low-level-calls": false,
+ "avoid-tx-origin": "warn",
+ "bracket-align": false,
+ "code-complexity": false,
+ "const-name-snakecase": "error",
+ "expression-indent": "error",
+ "function-max-lines": false,
+ "func-order": "error",
+ "indent": ["error", 4],
+ "max-line-length": ["warn", 160],
+ "no-inline-assembly": false,
+ "quotes": ["error", "double"],
+ "separate-by-one-line-in-contract": "error",
+ "space-after-comma": "error",
+ "statement-indent": "error"
+ }
+}
diff --git a/contracts/utils/README.md b/contracts/utils/README.md
new file mode 100644
index 000000000..e7c7b49ff
--- /dev/null
+++ b/contracts/utils/README.md
@@ -0,0 +1,70 @@
+## Contracts utils
+
+Smart contracts utils used in the 0x protocol.
+
+## Usage
+
+Contracts can be found in the [contracts](./contracts) directory. The contents of this directory are broken down into the following subdirectories:
+
+* [utils](./contracts/utils)
+ * This directory contains libraries and utils.
+* [test](./contracts/test)
+ * This directory contains mocks and other contracts that are used solely for testing contracts within the other directories.
+
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
+
+For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
+
+### Install Dependencies
+
+If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
+
+```bash
+yarn config set workspaces-experimental true
+```
+
+Then install dependencies
+
+```bash
+yarn install
+```
+
+### Build
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=@0x/contracts-utils yarn build
+```
+
+Or continuously rebuild on change:
+
+```bash
+PKG=@0x/contracts-utils yarn watch
+```
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
+
+### Run Tests
+
+```bash
+yarn test
+```
+
+#### Testing options
+
+Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
diff --git a/contracts/utils/compiler.json b/contracts/utils/compiler.json
new file mode 100644
index 000000000..1524c1eaa
--- /dev/null
+++ b/contracts/utils/compiler.json
@@ -0,0 +1,22 @@
+{
+ "artifactsDir": "./generated-artifacts",
+ "contractsDir": "./contracts",
+ "compilerSettings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode.object",
+ "evm.bytecode.sourceMap",
+ "evm.deployedBytecode.object",
+ "evm.deployedBytecode.sourceMap"
+ ]
+ }
+ }
+ },
+ "contracts": ["TestConstants", "TestLibBytes", "LibBytes", "Ownable", "IOwnable", "ReentrancyGuard", "SafeMath"]
+}
diff --git a/contracts/core/contracts/test/TestConstants/TestConstants.sol b/contracts/utils/contracts/test/TestConstants/TestConstants.sol
index 1275d007b..3c852173b 100644
--- a/contracts/core/contracts/test/TestConstants/TestConstants.sol
+++ b/contracts/utils/contracts/test/TestConstants/TestConstants.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
// solhint-disable max-line-length
diff --git a/contracts/core/contracts/test/TestLibBytes/TestLibBytes.sol b/contracts/utils/contracts/test/TestLibBytes/TestLibBytes.sol
index 00d861e61..444a3e717 100644
--- a/contracts/core/contracts/test/TestLibBytes/TestLibBytes.sol
+++ b/contracts/utils/contracts/test/TestLibBytes/TestLibBytes.sol
@@ -18,7 +18,7 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
+import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
contract TestLibBytes {
diff --git a/contracts/core/contracts/utils/LibBytes/LibBytes.sol b/contracts/utils/contracts/utils/LibBytes/LibBytes.sol
index 369f588ad..369f588ad 100644
--- a/contracts/core/contracts/utils/LibBytes/LibBytes.sol
+++ b/contracts/utils/contracts/utils/LibBytes/LibBytes.sol
diff --git a/contracts/core/contracts/utils/Ownable/IOwnable.sol b/contracts/utils/contracts/utils/Ownable/IOwnable.sol
index 5deb13497..5deb13497 100644
--- a/contracts/core/contracts/utils/Ownable/IOwnable.sol
+++ b/contracts/utils/contracts/utils/Ownable/IOwnable.sol
diff --git a/contracts/core/contracts/utils/Ownable/Ownable.sol b/contracts/utils/contracts/utils/Ownable/Ownable.sol
index 0c830be68..0c830be68 100644
--- a/contracts/core/contracts/utils/Ownable/Ownable.sol
+++ b/contracts/utils/contracts/utils/Ownable/Ownable.sol
diff --git a/contracts/core/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol b/contracts/utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol
index 9f98a7a16..9f98a7a16 100644
--- a/contracts/core/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol
+++ b/contracts/utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol
diff --git a/contracts/core/contracts/utils/SafeMath/SafeMath.sol b/contracts/utils/contracts/utils/SafeMath/SafeMath.sol
index 2855edb9d..2855edb9d 100644
--- a/contracts/core/contracts/utils/SafeMath/SafeMath.sol
+++ b/contracts/utils/contracts/utils/SafeMath/SafeMath.sol
diff --git a/contracts/utils/package.json b/contracts/utils/package.json
new file mode 100644
index 000000000..c0bc8bfcf
--- /dev/null
+++ b/contracts/utils/package.json
@@ -0,0 +1,90 @@
+{
+ "private": true,
+ "name": "@0x/contracts-utils",
+ "version": "1.0.0",
+ "engines": {
+ "node": ">=6.12"
+ },
+ "description": "Smart contract utils of 0x protocol",
+ "main": "lib/src/index.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "build": "yarn pre_build && tsc -b",
+ "build:ci": "yarn build",
+ "pre_build": "run-s compile generate_contract_wrappers",
+ "test": "yarn run_mocha",
+ "rebuild_and_test": "run-s build test",
+ "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
+ "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
+ "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
+ "run_mocha":
+ "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
+ "compile": "sol-compiler --contracts-dir contracts",
+ "clean": "shx rm -rf lib generated-artifacts generated-wrappers",
+ "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
+ "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
+ "coverage:report:text": "istanbul report text",
+ "coverage:report:html": "istanbul report html && open coverage/index.html",
+ "profiler:report:html": "istanbul report html && open coverage/index.html",
+ "coverage:report:lcov": "istanbul report lcov",
+ "test:circleci": "yarn test",
+ "lint-contracts": "solhint contracts/**/**/**/**/*.sol"
+ },
+ "config": {
+ "abis": "generated-artifacts/@(IOwnable|Ownable|LibBytes|ReentrancyGuard|SafeMath|TestConstants|TestLibBytes).json"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/0xProject/0x-monorepo.git"
+ },
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/0xProject/0x-monorepo/issues"
+ },
+ "homepage": "https://github.com/0xProject/0x-monorepo/contracts/utils/README.md",
+ "devDependencies": {
+ "@0x/contracts-test-utils": "^1.0.0",
+ "@0x/abi-gen": "^1.0.17",
+ "@0x/dev-utils": "^1.0.19",
+ "@0x/sol-compiler": "^1.1.14",
+ "@0x/sol-cov": "^2.1.14",
+ "@0x/subproviders": "^2.1.6",
+ "@0x/tslint-config": "^1.0.10",
+ "@types/bn.js": "^4.11.0",
+ "@types/lodash": "4.14.104",
+ "@types/node": "*",
+ "@types/yargs": "^10.0.0",
+ "bn.js": "^4.11.8",
+ "chai": "^4.0.1",
+ "chai-as-promised": "^7.1.0",
+ "chai-bignumber": "^2.0.1",
+ "dirty-chai": "^2.0.1",
+ "make-promises-safe": "^1.1.0",
+ "ethereumjs-abi": "0.6.5",
+ "mocha": "^4.1.0",
+ "npm-run-all": "^4.1.2",
+ "shx": "^0.2.2",
+ "solc": "^0.4.24",
+ "solhint": "^1.2.1",
+ "tslint": "5.11.0",
+ "typescript": "3.0.1",
+ "yargs": "^10.0.3"
+ },
+ "dependencies": {
+ "@0x/base-contract": "^3.0.8",
+ "@0x/order-utils": "^3.0.4",
+ "@0x/contracts-multisig": "^1.0.0",
+ "@0x/types": "^1.3.0",
+ "@0x/typescript-typings": "^3.0.4",
+ "@0x/utils": "^2.0.6",
+ "@0x/web3-wrapper": "^3.1.6",
+ "ethereum-types": "^1.1.2",
+ "ethereumjs-util": "^5.1.1",
+ "lodash": "^4.17.5"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/contracts/utils/src/artifacts/index.ts b/contracts/utils/src/artifacts/index.ts
new file mode 100644
index 000000000..a5c2b215c
--- /dev/null
+++ b/contracts/utils/src/artifacts/index.ts
@@ -0,0 +1,19 @@
+import { ContractArtifact } from 'ethereum-types';
+
+import * as IOwnable from '../../generated-artifacts/IOwnable.json';
+import * as LibBytes from '../../generated-artifacts/LibBytes.json';
+import * as Ownable from '../../generated-artifacts/Ownable.json';
+import * as ReentrancyGuard from '../../generated-artifacts/ReentrancyGuard.json';
+import * as SafeMath from '../../generated-artifacts/SafeMath.json';
+import * as TestConstants from '../../generated-artifacts/TestConstants.json';
+import * as TestLibBytes from '../../generated-artifacts/TestLibBytes.json';
+
+export const artifacts = {
+ TestConstants: TestConstants as ContractArtifact,
+ TestLibBytes: TestLibBytes as ContractArtifact,
+ IOwnable: IOwnable as ContractArtifact,
+ LibBytes: LibBytes as ContractArtifact,
+ Ownable: Ownable as ContractArtifact,
+ SafeMath: SafeMath as ContractArtifact,
+ ReentrancyGuard: ReentrancyGuard as ContractArtifact,
+};
diff --git a/contracts/utils/src/index.ts b/contracts/utils/src/index.ts
new file mode 100644
index 000000000..d55f08ea2
--- /dev/null
+++ b/contracts/utils/src/index.ts
@@ -0,0 +1,2 @@
+export * from './artifacts';
+export * from './wrappers';
diff --git a/contracts/utils/src/wrappers/index.ts b/contracts/utils/src/wrappers/index.ts
new file mode 100644
index 000000000..823b7fa4b
--- /dev/null
+++ b/contracts/utils/src/wrappers/index.ts
@@ -0,0 +1,2 @@
+export * from '../../generated-wrappers/test_constants';
+export * from '../../generated-wrappers/test_lib_bytes';
diff --git a/contracts/utils/test/global_hooks.ts b/contracts/utils/test/global_hooks.ts
new file mode 100644
index 000000000..f8ace376a
--- /dev/null
+++ b/contracts/utils/test/global_hooks.ts
@@ -0,0 +1,17 @@
+import { env, EnvVars } from '@0x/dev-utils';
+
+import { coverage, profiler, provider } from '@0x/contracts-test-utils';
+before('start web3 provider', () => {
+ provider.start();
+});
+after('generate coverage report', async () => {
+ if (env.parseBoolean(EnvVars.SolidityCoverage)) {
+ const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
+ await coverageSubprovider.writeCoverageAsync();
+ }
+ if (env.parseBoolean(EnvVars.SolidityProfiler)) {
+ const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
+ await profilerSubprovider.writeProfilerOutputAsync();
+ }
+ provider.stop();
+});
diff --git a/contracts/core/test/libraries/lib_bytes.ts b/contracts/utils/test/lib_bytes.ts
index b1a389f00..985a98943 100644
--- a/contracts/core/test/libraries/lib_bytes.ts
+++ b/contracts/utils/test/lib_bytes.ts
@@ -1,3 +1,12 @@
+import {
+ chaiSetup,
+ constants,
+ expectContractCallFailedAsync,
+ provider,
+ txDefaults,
+ typeEncodingUtils,
+ web3Wrapper,
+} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { generatePseudoRandomSalt } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
@@ -7,13 +16,8 @@ import * as chai from 'chai';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
-import { TestLibBytesContract } from '../../generated-wrappers/test_lib_bytes';
-import { artifacts } from '../../src/artifacts';
-import { expectContractCallFailedAsync } from '../utils/assertions';
-import { chaiSetup } from '../utils/chai_setup';
-import { constants } from '../utils/constants';
-import { typeEncodingUtils } from '../utils/type_encoding_utils';
-import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
+import { TestLibBytesContract } from '../generated-wrappers/test_lib_bytes';
+import { artifacts } from '../src';
chaiSetup.configure();
const expect = chai.expect;
diff --git a/contracts/utils/test/libs.ts b/contracts/utils/test/libs.ts
new file mode 100644
index 000000000..81596b2e4
--- /dev/null
+++ b/contracts/utils/test/libs.ts
@@ -0,0 +1,34 @@
+import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
+import { BlockchainLifecycle } from '@0x/dev-utils';
+import * as chai from 'chai';
+
+import { TestConstantsContract } from '../generated-wrappers/test_constants';
+import { artifacts } from '../src';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('Libs', () => {
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+
+ describe('LibConstants', () => {
+ describe('ZRX_ASSET_DATA', () => {
+ it('should have the correct ZRX_ASSET_DATA', async () => {
+ const testConstants = await TestConstantsContract.deployFrom0xArtifactAsync(
+ artifacts.TestConstants,
+ provider,
+ txDefaults,
+ );
+ const isValid = await testConstants.assertValidZrxAssetData.callAsync();
+ expect(isValid).to.be.equal(true);
+ });
+ });
+ });
+});
diff --git a/contracts/utils/tsconfig.json b/contracts/utils/tsconfig.json
new file mode 100644
index 000000000..68251e6b0
--- /dev/null
+++ b/contracts/utils/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "outDir": "lib",
+ "rootDir": ".",
+ "resolveJsonModule": true
+ },
+ "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
+ "files": [
+ "./generated-artifacts/TestConstants.json",
+ "./generated-artifacts/TestLibBytes.json",
+ "./generated-artifacts/IOwnable.json",
+ "./generated-artifacts/Ownable.json",
+ "./generated-artifacts/LibBytes.json",
+ "./generated-artifacts/SafeMath.json",
+ "./generated-artifacts/ReentrancyGuard.json"
+ ],
+ "exclude": ["./deploy/solc/solc_bin"]
+}
diff --git a/contracts/utils/tslint.json b/contracts/utils/tslint.json
new file mode 100644
index 000000000..1bb3ac2a2
--- /dev/null
+++ b/contracts/utils/tslint.json
@@ -0,0 +1,6 @@
+{
+ "extends": ["@0x/tslint-config"],
+ "rules": {
+ "custom-no-magic-numbers": false
+ }
+}
diff --git a/packages/0x.js/.npmignore b/packages/0x.js/.npmignore
index d7ee80c97..312a23faa 100644
--- a/packages/0x.js/.npmignore
+++ b/packages/0x.js/.npmignore
@@ -4,7 +4,7 @@ webpack.config.js
yarn-error.log
test/
/src/
-/contract_templates/
+/abi-gen-templates/
/generated_docs/
/scripts/
/lib/src/monorepo_scripts/
diff --git a/packages/abi-gen/README.md b/packages/abi-gen/README.md
index 20b9d4f30..214d8f257 100644
--- a/packages/abi-gen/README.md
+++ b/packages/abi-gen/README.md
@@ -4,7 +4,7 @@ This package allows you to generate TypeScript contract wrappers from ABI files.
It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach.
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
-[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate the contract wrappers used by 0x.js.e
+[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/abi-gen-templates) are the templates used to generate the contract wrappers used by 0x.js.e
## Installation
@@ -44,7 +44,7 @@ You need to also specify the location of your main template used for every contr
## How to write custom templates?
-The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates) and start adjusting them for your needs.
+The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen-templates) and start adjusting them for your needs.
We use [handlebars](http://handlebarsjs.com/) template engine under the hood.
You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available.
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json
index 28d3270e8..4ff83018e 100644
--- a/packages/asset-buyer/CHANGELOG.json
+++ b/packages/asset-buyer/CHANGELOG.json
@@ -1,5 +1,13 @@
[
{
+ "version": "3.0.3",
+ "changes": [
+ {
+ "note": "Update SRA order provider to include Dai"
+ }
+ ]
+ },
+ {
"timestamp": 1543401373,
"version": "3.0.2",
"changes": [
diff --git a/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts b/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts
index be1fc55d6..813c9923b 100644
--- a/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts
+++ b/packages/asset-buyer/src/order_providers/standard_relayer_api_order_provider.ts
@@ -100,6 +100,12 @@ export class StandardRelayerAPIOrderProvider implements OrderProvider {
} catch (err) {
throw new Error(AssetBuyerError.StandardRelayerApiError);
}
- return _.map(response.records, item => item.assetDataB.assetData);
+ return _.map(response.records, item => {
+ if (item.assetDataA.assetData === takerAssetData) {
+ return item.assetDataB.assetData;
+ } else {
+ return item.assetDataA.assetData;
+ }
+ });
}
}
diff --git a/packages/contract-wrappers/.npmignore b/packages/contract-wrappers/.npmignore
index 6a3eb57bd..6a222fd45 100644
--- a/packages/contract-wrappers/.npmignore
+++ b/packages/contract-wrappers/.npmignore
@@ -5,7 +5,7 @@ yarn-error.log
test/
/src/
/_bundles/
-/contract_templates/
+/abi-gen-templates/
/generated_docs/
/scripts/
/lib/src/monorepo_scripts/
diff --git a/packages/instant/.dogfood.discharge.json b/packages/instant/.dogfood.discharge.json
index 5d6a09a16..651b3daa6 100644
--- a/packages/instant/.dogfood.discharge.json
+++ b/packages/instant/.dogfood.discharge.json
@@ -1,6 +1,6 @@
{
"domain": "0x-instant-dogfood",
- "build_command": "WEBPACK_OUTPUT_PATH=public dotenv yarn build --env.discharge_target=dogfood",
+ "build_command": "WEBPACK_OUTPUT_PATH=public dotenv yarn build -- --env.discharge_target=dogfood",
"upload_directory": "public",
"index_key": "index.html",
"error_key": "index.html",
diff --git a/packages/instant/.env_example b/packages/instant/.env_example
index ebbbebc06..234e64bbe 100644
--- a/packages/instant/.env_example
+++ b/packages/instant/.env_example
@@ -1,4 +1,7 @@
INSTANT_ROLLBAR_PUBLISH_TOKEN=
INSTANT_ROLLBAR_CLIENT_TOKEN=
INSTANT_HEAP_ANALYTICS_ID_PRODUCTION=
-INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT= \ No newline at end of file
+INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT=
+# if you want to report to heap or rollbar when building in development mode, you can use the following:
+# INSTANT_HEAP_FORCE_DEVELOPMENT=true
+# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true \ No newline at end of file
diff --git a/packages/instant/.production.discharge.json b/packages/instant/.production.discharge.json
index 947f68b1a..1ce39fdd8 100644
--- a/packages/instant/.production.discharge.json
+++ b/packages/instant/.production.discharge.json
@@ -1,6 +1,6 @@
{
"domain": "instant.0xproject.com",
- "build_command": "dotenv yarn build --env.discharge_target=production",
+ "build_command": "dotenv yarn build -- --env.discharge_target=production",
"upload_directory": "umd",
"index_key": "instant.js",
"error_key": "404.html",
diff --git a/packages/instant/.staging.discharge.json b/packages/instant/.staging.discharge.json
index bd5f28ba8..844e3ca4e 100644
--- a/packages/instant/.staging.discharge.json
+++ b/packages/instant/.staging.discharge.json
@@ -1,6 +1,6 @@
{
"domain": "0x-instant-staging",
- "build_command": "dotenv WEBPACK_OUTPUT_PATH=public yarn build --env.discharge_target=staging",
+ "build_command": "WEBPACK_OUTPUT_PATH=public dotenv yarn build -- --env.discharge_target=staging",
"upload_directory": "public",
"index_key": "index.html",
"error_key": "index.html",
diff --git a/packages/instant/src/components/buy_order_progress.tsx b/packages/instant/src/components/buy_order_progress.tsx
index 6568de91b..a19f5a4d0 100644
--- a/packages/instant/src/components/buy_order_progress.tsx
+++ b/packages/instant/src/components/buy_order_progress.tsx
@@ -21,7 +21,7 @@ export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> =
const hasEnded = buyOrderState.processState !== OrderProcessState.Processing;
const expectedTimeMs = progress.expectedEndTimeUnix - progress.startTimeUnix;
return (
- <Container padding="20px 20px 0px 20px" width="100%">
+ <Container width="100%" padding="20px 20px 0px 20px">
<Container marginBottom="5px">
<TimeCounter estimatedTimeMs={expectedTimeMs} hasEnded={hasEnded} key={progress.startTimeUnix} />
</Container>
diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx
index ff900842a..4da82eb73 100644
--- a/packages/instant/src/components/erc20_asset_amount_input.tsx
+++ b/packages/instant/src/components/erc20_asset_amount_input.tsx
@@ -113,7 +113,7 @@ export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInput
);
};
private readonly _renderChevronIcon = (): React.ReactNode => {
- if (!this._areMultipleAssetsAvailable()) {
+ if (!this._areAnyAssetsAvailable()) {
return null;
}
return (
@@ -134,14 +134,14 @@ export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInput
// We don't want to allow opening the token selection panel if there are no assets.
// Since styles are inferred from the presence of a click handler, we want to return undefined
// instead of providing a noop.
- if (!this._areMultipleAssetsAvailable() || _.isUndefined(this.props.onSelectAssetClick)) {
+ if (!this._areAnyAssetsAvailable() || _.isUndefined(this.props.onSelectAssetClick)) {
return undefined;
}
return this._handleSelectAssetClick;
};
- private readonly _areMultipleAssetsAvailable = (): boolean => {
+ private readonly _areAnyAssetsAvailable = (): boolean => {
const { numberOfAssetsAvailable } = this.props;
- return !_.isUndefined(numberOfAssetsAvailable) && numberOfAssetsAvailable > 1;
+ return !_.isUndefined(numberOfAssetsAvailable) && numberOfAssetsAvailable > 0;
};
private readonly _handleSelectAssetClick = (): void => {
if (this.props.onSelectAssetClick) {
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
index 808c6dc7f..117f9dd5f 100644
--- a/packages/instant/src/components/instant_heading.tsx
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -32,7 +32,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
public render(): React.ReactNode {
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
return (
- <Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%">
+ <Container backgroundColor={ColorOption.primaryColor} width="100%" padding="20px">
<Container marginBottom="5px">
<Text
letterSpacing="1px"
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
index 5fc956e1c..a8e0e2513 100644
--- a/packages/instant/src/components/order_details.tsx
+++ b/packages/instant/src/components/order_details.tsx
@@ -34,7 +34,7 @@ export class OrderDetails extends React.Component<OrderDetailsProps> {
? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
: undefined;
return (
- <Container padding="20px" width="100%" flexGrow={1}>
+ <Container width="100%" flexGrow={1} padding="20px 20px 0px 20px">
<Container marginBottom="10px">
<Text
letterSpacing="1px"
diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx
index 4efe5b28e..603788748 100644
--- a/packages/instant/src/components/payment_method.tsx
+++ b/packages/instant/src/components/payment_method.tsx
@@ -26,7 +26,7 @@ export interface PaymentMethodProps {
export class PaymentMethod extends React.Component<PaymentMethodProps> {
public render(): React.ReactNode {
return (
- <Container padding="20px" width="100%" height="133px">
+ <Container width="100%" height="120px" padding="20px 20px 0px 20px">
<Container marginBottom="12px">
<Flex justify="space-between">
<Text
diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts
index 1194cf881..2439c7349 100644
--- a/packages/instant/src/constants.ts
+++ b/packages/instant/src/constants.ts
@@ -19,6 +19,7 @@ export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.mul(6);
export const DEFAULT_ESTIMATED_TRANSACTION_TIME_MS = ONE_MINUTE_MS * 2;
export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
export const HEAP_ANALYTICS_ID = process.env.HEAP_ANALYTICS_ID;
+export const HEAP_ENABLED = process.env.HEAP_ENABLED;
export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';
export const PROGRESS_STALL_AT_WIDTH = '95%';
export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200;
diff --git a/packages/instant/src/data/asset_meta_data_map.ts b/packages/instant/src/data/asset_meta_data_map.ts
index 0553be7f5..88611a8c0 100644
--- a/packages/instant/src/data/asset_meta_data_map.ts
+++ b/packages/instant/src/data/asset_meta_data_map.ts
@@ -195,7 +195,7 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
'0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359': {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
- primaryColor: '#F2B350',
+ primaryColor: '#DEA349',
symbol: 'dai',
name: 'Dai Stablecoin',
},
diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts
index 18f671cd7..c67b222d1 100644
--- a/packages/instant/src/redux/async_data.ts
+++ b/packages/instant/src/redux/async_data.ts
@@ -32,7 +32,8 @@ export const asyncData = {
const assetBuyer = providerState.assetBuyer;
try {
const assetDatas = await assetBuyer.getAvailableAssetDatasAsync();
- const assets = assetUtils.createAssetsFromAssetDatas(assetDatas, assetMetaDataMap, network);
+ const deduplicatedAssetDatas = _.uniq(assetDatas);
+ const assets = assetUtils.createAssetsFromAssetDatas(deduplicatedAssetDatas, assetMetaDataMap, network);
dispatch(actions.setAvailableAssets(assets));
} catch (e) {
const errorMessage = 'Could not find any assets';
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
index 4bc4e7c6d..3ab5c55fc 100644
--- a/packages/instant/src/util/analytics.ts
+++ b/packages/instant/src/util/analytics.ts
@@ -2,7 +2,7 @@ import { BuyQuote } from '@0x/asset-buyer';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
-import { INSTANT_DISCHARGE_TARGET } from '../constants';
+import { HEAP_ENABLED, INSTANT_DISCHARGE_TARGET } from '../constants';
import {
AffiliateInfo,
Asset,
@@ -16,15 +16,17 @@ import {
import { EventProperties, heapUtil } from './heap';
-let isDisabled = false;
+let isDisabledViaConfig = false;
export const disableAnalytics = (shouldDisableAnalytics: boolean) => {
- isDisabled = shouldDisableAnalytics;
+ isDisabledViaConfig = shouldDisableAnalytics;
};
export const evaluateIfEnabled = (fnCall: () => void) => {
- if (isDisabled) {
+ if (isDisabledViaConfig) {
return;
}
- fnCall();
+ if (HEAP_ENABLED) {
+ fnCall();
+ }
};
enum EventNames {
diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js
index a1db01db9..e74cf36d9 100644
--- a/packages/instant/webpack.config.js
+++ b/packages/instant/webpack.config.js
@@ -71,6 +71,7 @@ const generateConfig = (dischargeTarget, heapConfigOptions, rollbarConfigOptions
`Must define heap analytics id in ENV var ${heapAnalyticsIdEnvName} when building for ${dischargeTarget}`,
);
}
+ const heapEnabled = heapAnalyticsId && (nodeEnv !== 'development' || process.env.INSTANT_HEAP_FORCE_DEVELOPMENT);
const rollbarTokens = getRollbarTokens(dischargeTarget, rollbarConfigOptions.rollbarRequired);
const rollbarEnabled =
@@ -92,6 +93,7 @@ const generateConfig = (dischargeTarget, heapConfigOptions, rollbarConfigOptions
GIT_SHA: JSON.stringify(GIT_SHA),
NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version),
ROLLBAR_ENABLED: rollbarEnabled,
+ HEAP_ENABLED: heapEnabled
};
if (dischargeTarget) {
envVars.INSTANT_DISCHARGE_TARGET = JSON.stringify(dischargeTarget);
diff --git a/packages/monorepo-scripts/CHANGELOG.json b/packages/monorepo-scripts/CHANGELOG.json
index 170a97a33..428168437 100644
--- a/packages/monorepo-scripts/CHANGELOG.json
+++ b/packages/monorepo-scripts/CHANGELOG.json
@@ -13,6 +13,10 @@
{
"note": "Add ForwarderError to the IGNORED_EXCESSIVE_TYPES array",
"pr": 1147
+ },
+ {
+ "note": "Fix a bug when hardcoded CHANGELOG paths cause fetching release notes to fail",
+ "pr": 1311
}
]
},
diff --git a/packages/monorepo-scripts/src/utils/github_release_utils.ts b/packages/monorepo-scripts/src/utils/github_release_utils.ts
index 7434d397e..e63244b46 100644
--- a/packages/monorepo-scripts/src/utils/github_release_utils.ts
+++ b/packages/monorepo-scripts/src/utils/github_release_utils.ts
@@ -41,7 +41,7 @@ export async function publishReleaseNotesAsync(packagesToPublish: Package[], isD
let assets: string[] = [];
let aggregateNotes = '';
_.each(packagesToPublish, pkg => {
- aggregateNotes += getReleaseNotesForPackage(pkg.packageJson.name);
+ aggregateNotes += getReleaseNotesForPackage(pkg.location, pkg.packageJson.name);
const packageAssets = _.get(pkg.packageJson, 'config.postpublish.assets');
if (!_.isUndefined(packageAssets)) {
@@ -88,14 +88,8 @@ function adjustAssetPaths(assets: string[]): string[] {
return finalAssets;
}
-function getReleaseNotesForPackage(packageName: string): string {
- const packageNameWithoutNamespace = packageName.replace('@0x/', '');
- const changelogJSONPath = path.join(
- constants.monorepoRootPath,
- 'packages',
- packageNameWithoutNamespace,
- 'CHANGELOG.json',
- );
+function getReleaseNotesForPackage(packageLocation: string, packageName: string): string {
+ const changelogJSONPath = path.join(packageLocation, 'CHANGELOG.json');
const changelogJSON = readFileSync(changelogJSONPath, 'utf-8');
const changelogs = JSON.parse(changelogJSON);
const latestLog = changelogs[0];
diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json
index e9274f64e..fe077b6cc 100644
--- a/packages/sol-compiler/CHANGELOG.json
+++ b/packages/sol-compiler/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "1.1.15",
+ "changes": [
+ {
+ "note": "Fix bug where we were appending base path to absolute imports (e.g NPM imports)",
+ "pr": 1311
+ }
+ ]
+ },
+ {
"timestamp": 1543401373,
"version": "1.1.14",
"changes": [
diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts
index 8ee7fa4a9..cba67f292 100644
--- a/packages/sol-compiler/src/compiler.ts
+++ b/packages/sol-compiler/src/compiler.ts
@@ -394,7 +394,14 @@ export class Compiler {
//
const lastPathSeparatorPos = contractPath.lastIndexOf('/');
const contractFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1);
- importPath = path.resolve('/' + contractFolder, importPath).replace('/', '');
+ if (importPath.startsWith('.')) {
+ /**
+ * Some imports path are relative ("../Token.sol", "./Wallet.sol")
+ * while others are absolute ("Token.sol", "@0x/contracts/Wallet.sol")
+ * And we need to append the base path for relative imports.
+ */
+ importPath = path.resolve('/' + contractFolder, importPath).replace('/', '');
+ }
if (_.isUndefined(sourcesToAppendTo[importPath])) {
sourcesToAppendTo[importPath] = { id: fullSources[importPath].id };
diff --git a/packages/sol-resolver/CHANGELOG.json b/packages/sol-resolver/CHANGELOG.json
index fdfb4009b..4c9e612d7 100644
--- a/packages/sol-resolver/CHANGELOG.json
+++ b/packages/sol-resolver/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "1.1.0",
+ "changes": [
+ {
+ "note": "NPMResolver now supports scoped packages",
+ "pr": 1311
+ }
+ ]
+ },
+ {
"timestamp": 1542821676,
"version": "1.0.17",
"changes": [
diff --git a/packages/sol-resolver/src/resolvers/npm_resolver.ts b/packages/sol-resolver/src/resolvers/npm_resolver.ts
index a2df0dcad..eeb2b5493 100644
--- a/packages/sol-resolver/src/resolvers/npm_resolver.ts
+++ b/packages/sol-resolver/src/resolvers/npm_resolver.ts
@@ -1,4 +1,5 @@
import * as fs from 'fs';
+import * as _ from 'lodash';
import * as path from 'path';
import { ContractSource } from '../types';
@@ -13,12 +14,22 @@ export class NPMResolver extends Resolver {
}
public resolveIfExists(importPath: string): ContractSource | undefined {
if (!importPath.startsWith('/')) {
- const [packageName, ...other] = importPath.split('/');
+ let packageName;
+ let packageScopeIfExists;
+ let other;
+ if (_.startsWith(importPath, '@')) {
+ [packageScopeIfExists, packageName, ...other] = importPath.split('/');
+ } else {
+ [packageName, ...other] = importPath.split('/');
+ }
const pathWithinPackage = path.join(...other);
let currentPath = this._packagePath;
const ROOT_PATH = '/';
while (currentPath !== ROOT_PATH) {
- const lookupPath = path.join(currentPath, 'node_modules', packageName, pathWithinPackage);
+ const packagePath = _.isUndefined(packageScopeIfExists)
+ ? packageName
+ : path.join(packageScopeIfExists, packageName);
+ const lookupPath = path.join(currentPath, 'node_modules', packagePath, pathWithinPackage);
if (fs.existsSync(lookupPath) && fs.lstatSync(lookupPath).isFile()) {
const fileContent = fs.readFileSync(lookupPath).toString();
return {
diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json
index 53b24aff0..b09859101 100644
--- a/packages/types/CHANGELOG.json
+++ b/packages/types/CHANGELOG.json
@@ -5,6 +5,10 @@
{
"note": "Add `LengthMismatch` and `LengthGreaterThan3Required` revert reasons",
"pr": 1224
+ },
+ {
+ "note": "Add RevertReasons for DutchAuction contract",
+ "pr": 1225
}
]
},
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 26d8f8e22..6b728af71 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -237,6 +237,12 @@ export enum RevertReason {
TxFullyConfirmed = 'TX_FULLY_CONFIRMED',
TxNotFullyConfirmed = 'TX_NOT_FULLY_CONFIRMED',
TimeLockIncomplete = 'TIME_LOCK_INCOMPLETE',
+ // DutchAuction
+ AuctionInvalidAmount = 'INVALID_AMOUNT',
+ AuctionExpired = 'AUCTION_EXPIRED',
+ AuctionNotStarted = 'AUCTION_NOT_STARTED',
+ AuctionInvalidBeginTime = 'INVALID_BEGIN_TIME',
+ InvalidAssetData = 'INVALID_ASSET_DATA',
}
export enum StatusCodes {