Merge remote-tracking branch 'upstream/development' into website
# Conflicts: # packages/website/package.json # packages/website/ts/style/colors.ts
This commit is contained in:
commit
00dbddc1aa
@ -40,7 +40,10 @@ 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-libs
|
||||
- run: yarn wsrun test:circleci @0x/contracts-core
|
||||
test-contracts-geth:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
@ -52,7 +55,10 @@ 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-libs
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test @0x/contracts-core
|
||||
test-publish:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
@ -81,6 +87,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
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -82,13 +82,19 @@ packages/react-docs/example/public/bundle*
|
||||
packages/testnet-faucets/server/
|
||||
|
||||
# generated contract artifacts/
|
||||
packages/contracts/generated-artifacts/
|
||||
contracts/core/generated-artifacts/
|
||||
contracts/multisig/generated-artifacts/
|
||||
contracts/utils/generated-artifacts/
|
||||
contracts/libs/generated-artifacts/
|
||||
packages/sol-cov/test/fixtures/artifacts/
|
||||
packages/metacoin/artifacts/
|
||||
|
||||
# generated contract wrappers
|
||||
packages/abi-gen-wrappers/wrappers
|
||||
packages/contracts/generated-wrappers/
|
||||
contracts/core/generated-wrappers/
|
||||
contracts/multisig/generated-wrappers/
|
||||
contracts/utils/generated-wrappers/
|
||||
contracts/libs/generated-wrappers/
|
||||
packages/metacoin/src/contract_wrappers
|
||||
|
||||
# solc-bin in sol-compiler
|
||||
|
@ -1,7 +1,13 @@
|
||||
lib
|
||||
.nyc_output
|
||||
/packages/contracts/generated-wrappers
|
||||
/packages/contracts/generated-artifacts
|
||||
/contracts/core/generated-wrappers
|
||||
/contracts/core/generated-artifacts
|
||||
/contracts/multisig/generated-wrappers
|
||||
/contracts/multisig/generated-artifacts
|
||||
/contracts/utils/generated-wrappers
|
||||
/contracts/utils/generated-artifacts
|
||||
/contracts/libs/generated-wrappers
|
||||
/contracts/libs/generated-artifacts
|
||||
/packages/abi-gen-wrappers/src/generated-wrappers
|
||||
/packages/contract-artifacts/artifacts
|
||||
/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
|
||||
|
@ -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
|
||||
@ -32,4 +32,4 @@ packages/web3-wrapper/ @LogvinovLeon @fabioberger
|
||||
python-packages/ @feuGeneA
|
||||
|
||||
# Protocol/smart contracts
|
||||
packages/contracts/test/ @albrow
|
||||
contracts/core/test/ @albrow
|
||||
|
@ -78,7 +78,7 @@ Visit our [developer portal](https://0xproject.com/docs/order-utils) for a compr
|
||||
|
||||
| Package | Description |
|
||||
| -------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| [`@0x/contracts`](/packages/contracts) | 0x protocol solidity smart contracts & tests |
|
||||
| [`@0x/contracts`](/contracts/core) | 0x protocol solidity smart contracts & tests |
|
||||
| [`@0x/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0x/website`](/packages/website) | 0x website |
|
||||
|
||||
|
48
contracts/TESTING.md
Normal file
48
contracts/TESTING.md
Normal file
@ -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.
|
@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"name": "MultiAssetProxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add MultiAssetProxy implementation",
|
||||
"pr": 1224
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OrderValidator",
|
||||
"version": "1.0.1",
|
@ -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).
|
@ -25,6 +25,7 @@
|
||||
"DummyERC721Token",
|
||||
"DummyMultipleReturnERC20Token",
|
||||
"DummyNoReturnERC20Token",
|
||||
"DutchAuction",
|
||||
"ERC20Proxy",
|
||||
"ERC20Token",
|
||||
"ERC721Token",
|
||||
@ -38,15 +39,11 @@
|
||||
"IValidator",
|
||||
"IWallet",
|
||||
"MixinAuthorizable",
|
||||
"MultiSigWallet",
|
||||
"MultiSigWalletWithTimeLock",
|
||||
"MultiAssetProxy",
|
||||
"OrderValidator",
|
||||
"ReentrantERC20Token",
|
||||
"TestAssetProxyOwner",
|
||||
"TestAssetProxyDispatcher",
|
||||
"TestConstants",
|
||||
"TestLibBytes",
|
||||
"TestLibs",
|
||||
"TestExchangeInternals",
|
||||
"TestSignatureValidator",
|
||||
"TestStaticCallReceiver",
|
@ -20,7 +20,7 @@ pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/interfaces/IExchange.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
|
||||
|
||||
contract ExchangeWrapper {
|
@ -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
|
@ -20,8 +20,8 @@ pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/interfaces/IExchange.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../utils/Ownable/Ownable.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/Ownable/Ownable.sol";
|
||||
|
||||
|
||||
contract Whitelist is
|
@ -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 "@0x/contracts-libs/contracts/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;
|
||||
}
|
||||
}
|
@ -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";
|
@ -21,10 +21,10 @@ pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MExchangeWrapper.sol";
|
||||
import "../../protocol/Exchange/libs/LibAbiEncoder.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "../../protocol/Exchange/libs/LibMath.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibAbiEncoder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
|
||||
|
||||
contract MixinExchangeWrapper is
|
@ -24,10 +24,10 @@ import "./mixins/MWeth.sol";
|
||||
import "./mixins/MAssets.sol";
|
||||
import "./mixins/MExchangeWrapper.sol";
|
||||
import "./interfaces/IForwarderCore.sol";
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "../../protocol/Exchange/libs/LibMath.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
|
||||
|
||||
contract MixinForwarderCore is
|
@ -18,7 +18,7 @@
|
||||
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "../../protocol/Exchange/libs/LibMath.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./mixins/MWeth.sol";
|
||||
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IForwarderCore {
|
@ -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";
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract MExchangeWrapper {
|
@ -20,10 +20,10 @@ pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/interfaces/IExchange.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/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 {
|
@ -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";
|
||||
|
||||
|
300
contracts/core/contracts/protocol/AssetProxy/MultiAssetProxy.sol
Normal file
300
contracts/core/contracts/protocol/AssetProxy/MultiAssetProxy.sol
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
|
||||
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;
|
||||
|
||||
import "../Exchange/MixinAssetProxyDispatcher.sol";
|
||||
import "./MixinAuthorizable.sol";
|
||||
|
||||
|
||||
contract MultiAssetProxy is
|
||||
MixinAssetProxyDispatcher,
|
||||
MixinAuthorizable
|
||||
{
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
|
||||
|
||||
// solhint-disable-next-line payable-fallback
|
||||
function ()
|
||||
external
|
||||
{
|
||||
assembly {
|
||||
// The first 4 bytes of calldata holds the function selector
|
||||
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// `transferFrom` will be called with the following parameters:
|
||||
// assetData Encoded byte array.
|
||||
// from Address to transfer asset from.
|
||||
// to Address to transfer asset to.
|
||||
// amount Amount of asset to transfer.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
|
||||
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
mstore(0, caller)
|
||||
mstore(32, authorized_slot)
|
||||
|
||||
// Revert if authorized[msg.sender] == false
|
||||
if iszero(sload(keccak256(0, 64))) {
|
||||
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// `transferFrom`.
|
||||
// The function is marked `external`, so no abi decoding is done for
|
||||
// us. Instead, we expect the `calldata` memory to contain the
|
||||
// following:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | ** | assetData Contents |
|
||||
//
|
||||
// (*): offset is computed from start of function parameters, so offset
|
||||
// by an additional 4 bytes in the calldata.
|
||||
//
|
||||
// (**): see table below to compute length of assetData Contents
|
||||
//
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
|
||||
// Load offset to `assetData`
|
||||
let assetDataOffset := calldataload(4)
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|-------------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | assetProxyId |
|
||||
// | Params | | 2 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to amounts (*) |
|
||||
// | | 36 | | 2. offset to nestedAssetData (*) |
|
||||
// | Data | | | amounts: |
|
||||
// | | 68 | 32 | amounts Length |
|
||||
// | | 100 | a | amounts Contents |
|
||||
// | | | | nestedAssetData: |
|
||||
// | | 100 + a | 32 | nestedAssetData Length |
|
||||
// | | 132 + a | b | nestedAssetData Contents (offsets) |
|
||||
// | | 132 + a + b | | nestedAssetData[0, ..., len] |
|
||||
|
||||
// In order to find the offset to `amounts`, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
let amountsOffset := calldataload(add(assetDataOffset, 40))
|
||||
|
||||
// In order to find the offset to `nestedAssetData`, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + 32 (amounts offset)
|
||||
let nestedAssetDataOffset := calldataload(add(assetDataOffset, 72))
|
||||
|
||||
// In order to find the start of the `amounts` contents, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + amountsOffset
|
||||
// + 32 (amounts len)
|
||||
let amountsContentsStart := add(assetDataOffset, add(amountsOffset, 72))
|
||||
|
||||
// Load number of elements in `amounts`
|
||||
let amountsLen := calldataload(sub(amountsContentsStart, 32))
|
||||
|
||||
// In order to find the start of the `nestedAssetData` contents, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
let nestedAssetDataContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, 72))
|
||||
|
||||
// Load number of elements in `nestedAssetData`
|
||||
let nestedAssetDataLen := calldataload(sub(nestedAssetDataContentsStart, 32))
|
||||
|
||||
// Revert if number of elements in `amounts` differs from number of elements in `nestedAssetData`
|
||||
if iszero(eq(amountsLen, nestedAssetDataLen)) {
|
||||
// Revert with `Error("LENGTH_MISMATCH")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000000f4c454e4754485f4d49534d4154434800000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Copy `transferFrom` selector, offset to `assetData`, `from`, and `to` from calldata to memory
|
||||
calldatacopy(
|
||||
0, // memory can safely be overwritten from beginning
|
||||
0, // start of calldata
|
||||
100 // length of selector (4) and 3 params (32 * 3)
|
||||
)
|
||||
|
||||
// Overwrite existing offset to `assetData` with our own
|
||||
mstore(4, 128)
|
||||
|
||||
// Load `amount`
|
||||
let amount := calldataload(100)
|
||||
|
||||
// Calculate number of bytes in `amounts` contents
|
||||
let amountsByteLen := mul(amountsLen, 32)
|
||||
|
||||
// Initialize `assetProxyId` and `assetProxy` to 0
|
||||
let assetProxyId := 0
|
||||
let assetProxy := 0
|
||||
|
||||
// Loop through `amounts` and `nestedAssetData`, calling `transferFrom` for each respective element
|
||||
for {let i := 0} lt(i, amountsByteLen) {i := add(i, 32)} {
|
||||
|
||||
// Calculate the total amount
|
||||
let amountsElement := calldataload(add(amountsContentsStart, i))
|
||||
let totalAmount := mul(amountsElement, amount)
|
||||
|
||||
// Revert if multiplication resulted in an overflow
|
||||
if iszero(eq(div(totalAmount, amount), amountsElement)) {
|
||||
// Revert with `Error("UINT256_OVERFLOW")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Write `totalAmount` to memory
|
||||
mstore(100, totalAmount)
|
||||
|
||||
// Load offset to `nestedAssetData[i]`
|
||||
let nestedAssetDataElementOffset := calldataload(add(nestedAssetDataContentsStart, i))
|
||||
|
||||
// In order to find the start of the `nestedAssetData[i]` contents, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
// + nestedAssetDataElementOffset
|
||||
// + 32 (nestedAssetDataElement len)
|
||||
let nestedAssetDataElementContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, add(nestedAssetDataElementOffset, 104)))
|
||||
|
||||
// Load length of `nestedAssetData[i]`
|
||||
let nestedAssetDataElementLenStart := sub(nestedAssetDataElementContentsStart, 32)
|
||||
let nestedAssetDataElementLen := calldataload(nestedAssetDataElementLenStart)
|
||||
|
||||
// Revert if the `nestedAssetData` does not contain a 4 byte `assetProxyId`
|
||||
if lt(nestedAssetDataElementLen, 4) {
|
||||
// Revert with `Error("LENGTH_GREATER_THAN_3_REQUIRED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001e4c454e4754485f475245415445525f5448414e5f335f524551554952)
|
||||
mstore(96, 0x4544000000000000000000000000000000000000000000000000000000000000)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Load AssetProxy id
|
||||
let currentAssetProxyId := and(
|
||||
calldataload(nestedAssetDataElementContentsStart),
|
||||
0xffffffff00000000000000000000000000000000000000000000000000000000
|
||||
)
|
||||
|
||||
// Only load `assetProxy` if `currentAssetProxyId` does not equal `assetProxyId`
|
||||
// We do not need to check if `currentAssetProxyId` is 0 since `assetProxy` is also initialized to 0
|
||||
if iszero(eq(currentAssetProxyId, assetProxyId)) {
|
||||
// Update `assetProxyId`
|
||||
assetProxyId := currentAssetProxyId
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
mstore(132, assetProxyId)
|
||||
mstore(164, assetProxies_slot)
|
||||
assetProxy := sload(keccak256(132, 64))
|
||||
}
|
||||
|
||||
// Revert if AssetProxy with given id does not exist
|
||||
if iszero(assetProxy) {
|
||||
// Revert with `Error("ASSET_PROXY_DOES_NOT_EXIST")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001a41535345545f50524f58595f444f45535f4e4f545f45584953540000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Copy `nestedAssetData[i]` from calldata to memory
|
||||
calldatacopy(
|
||||
132, // memory slot after `amounts[i]`
|
||||
nestedAssetDataElementLenStart, // location of `nestedAssetData[i]` in calldata
|
||||
add(nestedAssetDataElementLen, 32) // `nestedAssetData[i].length` plus 32 byte length
|
||||
)
|
||||
|
||||
// call `assetProxy.transferFrom`
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
assetProxy, // call address of asset proxy
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
add(164, nestedAssetDataElementLen), // length of input
|
||||
0, // write output over memory that won't be reused
|
||||
0 // don't copy output to memory
|
||||
)
|
||||
|
||||
// Revert with reason given by AssetProxy if `transferFrom` call failed
|
||||
if iszero(success) {
|
||||
returndatacopy(
|
||||
0, // copy to memory at 0
|
||||
0, // copy from return data at 0
|
||||
returndatasize() // copy all return data
|
||||
)
|
||||
revert(0, returndatasize())
|
||||
}
|
||||
}
|
||||
|
||||
// Return if no `transferFrom` calls reverted
|
||||
return(0, 0)
|
||||
}
|
||||
|
||||
// Revert if undefined function is called
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
// @dev Interface of the asset proxy's assetData.
|
||||
@ -26,15 +27,18 @@ pragma solidity 0.4.24;
|
||||
interface IAssetData {
|
||||
|
||||
function ERC20Token(address tokenContract)
|
||||
external
|
||||
pure;
|
||||
external;
|
||||
|
||||
function ERC721Token(
|
||||
address tokenContract,
|
||||
uint256 tokenId,
|
||||
bytes receiverData
|
||||
uint256 tokenId
|
||||
)
|
||||
external
|
||||
pure;
|
||||
external;
|
||||
|
||||
function MultiAsset(
|
||||
uint256[] amounts,
|
||||
bytes[] nestedAssetData
|
||||
)
|
||||
external;
|
||||
|
||||
}
|
@ -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
|
@ -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
|
@ -19,7 +19,7 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./libs/LibConstants.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibConstants.sol";
|
||||
import "./MixinExchangeCore.sol";
|
||||
import "./MixinSignatureValidator.sol";
|
||||
import "./MixinWrapperFunctions.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";
|
||||
|
@ -19,11 +19,11 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibConstants.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
@ -14,11 +14,11 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "./libs/LibConstants.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibConstants.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./mixins/MMatchOrders.sol";
|
||||
import "./mixins/MTransactions.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
|
||||
)
|
@ -17,10 +17,10 @@
|
||||
*/
|
||||
pragma solidity 0.4.24;
|
||||
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibExchangeErrors.sol";
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
||||
import "./libs/LibEIP712.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibEIP712.sol";
|
||||
|
||||
|
||||
contract MixinTransactions is
|
@ -19,11 +19,11 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
import "./libs/LibAbiEncoder.sol";
|
||||
import "@0x/contracts-utils/contracts/utils/ReentrancyGuard/ReentrancyGuard.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibMath.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibAbiEncoder.sol";
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./mixins/MWrapperFunctions.sol";
|
||||
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IExchangeCore {
|
@ -18,8 +18,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IMatchOrders {
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
|
||||
|
||||
contract IWrapperFunctions {
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "../interfaces/IExchangeCore.sol";
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "../interfaces/IMatchOrders.sol";
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
pragma solidity 0.4.24;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
import "@0x/contracts-libs/contracts/libs/LibFillResults.sol";
|
||||
import "../interfaces/IWrapperFunctions.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";
|
||||
|
||||
|
@ -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
|
@ -19,10 +19,10 @@
|
||||
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";
|
||||
import "@0x/contracts-libs/contracts/libs/LibOrder.sol";
|
||||
|
||||
|
||||
// solhint-disable no-unused-vars
|
||||
@ -92,53 +92,53 @@ contract ReentrantERC20Token is
|
||||
LibOrder.Order[] memory orders;
|
||||
uint256[] memory takerAssetFillAmounts;
|
||||
bytes[] memory signatures;
|
||||
bytes memory calldata;
|
||||
bytes memory callData;
|
||||
|
||||
// Create calldata for function that corresponds to currentFunctionId
|
||||
// Create callData for function that corresponds to currentFunctionId
|
||||
if (currentFunctionId == uint8(ExchangeFunction.FILL_ORDER)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.fillOrder.selector,
|
||||
order,
|
||||
0,
|
||||
signature
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.FILL_OR_KILL_ORDER)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.fillOrKillOrder.selector,
|
||||
order,
|
||||
0,
|
||||
signature
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.BATCH_FILL_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.batchFillOrders.selector,
|
||||
orders,
|
||||
takerAssetFillAmounts,
|
||||
signatures
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.BATCH_FILL_OR_KILL_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.batchFillOrKillOrders.selector,
|
||||
orders,
|
||||
takerAssetFillAmounts,
|
||||
signatures
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.MARKET_BUY_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.marketBuyOrders.selector,
|
||||
orders,
|
||||
0,
|
||||
signatures
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.MARKET_SELL_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.marketSellOrders.selector,
|
||||
orders,
|
||||
0,
|
||||
signatures
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.MATCH_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.matchOrders.selector,
|
||||
order,
|
||||
order,
|
||||
@ -146,22 +146,22 @@ contract ReentrantERC20Token is
|
||||
signature
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDER)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.cancelOrder.selector,
|
||||
order
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.BATCH_CANCEL_ORDERS)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.batchCancelOrders.selector,
|
||||
orders
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDERS_UP_TO)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.cancelOrdersUpTo.selector,
|
||||
0
|
||||
);
|
||||
} else if (currentFunctionId == uint8(ExchangeFunction.SET_SIGNATURE_VALIDATOR_APPROVAL)) {
|
||||
calldata = abi.encodeWithSelector(
|
||||
callData = abi.encodeWithSelector(
|
||||
EXCHANGE.setSignatureValidatorApproval.selector,
|
||||
address(0),
|
||||
false
|
||||
@ -169,7 +169,7 @@ contract ReentrantERC20Token is
|
||||
}
|
||||
|
||||
// Call Exchange function, swallow error
|
||||
address(EXCHANGE).call(calldata);
|
||||
address(EXCHANGE).call(callData);
|
||||
|
||||
// Revert reason is 100 bytes
|
||||
bytes memory returnData = new bytes(100);
|
@ -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";
|
||||
|
||||
|
@ -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
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "contracts",
|
||||
"version": "2.1.55",
|
||||
"name": "@0x/contracts-core",
|
||||
"version": "2.1.56",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -19,7 +19,8 @@
|
||||
"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",
|
||||
"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",
|
||||
@ -32,27 +33,26 @@
|
||||
"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|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|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/packages/contracts/README.md",
|
||||
"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/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/ethereumjs-abi": "^0.6.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^10.0.0",
|
||||
@ -61,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",
|
||||
@ -71,19 +72,19 @@
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.7",
|
||||
"@0x/order-utils": "^3.0.3",
|
||||
"@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/contracts-libs": "^1.0.0",
|
||||
"@0x/types": "^1.3.0",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.6",
|
||||
"@0x/web3-wrapper": "^3.1.5",
|
||||
"@0x/web3-wrapper": "^3.1.6",
|
||||
"@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": {
|
@ -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';
|
||||
@ -19,16 +20,12 @@ import * as InvalidERC721Receiver from '../../generated-artifacts/InvalidERC721R
|
||||
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 MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
|
||||
import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
|
||||
import * as MultiAssetProxy from '../../generated-artifacts/MultiAssetProxy.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';
|
||||
import * as Validator from '../../generated-artifacts/Validator.json';
|
||||
@ -44,6 +41,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,
|
||||
@ -57,16 +55,12 @@ export const artifacts = {
|
||||
IWallet: IWallet as ContractArtifact,
|
||||
InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact,
|
||||
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
|
||||
MultiSigWallet: MultiSigWallet as ContractArtifact,
|
||||
MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
|
||||
MultiAssetProxy: MultiAssetProxy 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,
|
||||
Validator: Validator as ContractArtifact,
|
@ -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,16 +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';
|
||||
export * from '../../generated-wrappers/validator';
|
@ -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;
|
1251
contracts/core/test/asset_proxy/proxies.ts
Normal file
1251
contracts/core/test/asset_proxy/proxies.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -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';
|
||||
@ -14,23 +27,23 @@ import { DummyNoReturnERC20TokenContract } from '../../generated-wrappers/dummy_
|
||||
import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy';
|
||||
import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
|
||||
import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated-wrappers/exchange';
|
||||
import { IAssetDataContract } from '../../generated-wrappers/i_asset_data';
|
||||
import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_proxy';
|
||||
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;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
const assetDataInterface = new IAssetDataContract(
|
||||
artifacts.IAssetData.compilerOutput.abi,
|
||||
constants.NULL_ADDRESS,
|
||||
provider,
|
||||
);
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
describe('Exchange core', () => {
|
||||
let makerAddress: string;
|
||||
@ -47,6 +60,7 @@ describe('Exchange core', () => {
|
||||
let exchange: ExchangeContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let erc721Proxy: ERC721ProxyContract;
|
||||
let multiAssetProxy: MultiAssetProxyContract;
|
||||
let maliciousWallet: TestStaticCallReceiverContract;
|
||||
let maliciousValidator: TestStaticCallReceiverContract;
|
||||
|
||||
@ -76,44 +90,26 @@ describe('Exchange core', () => {
|
||||
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
||||
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
|
||||
|
||||
// Deploy AssetProxies, Exchange, tokens, and malicious contracts
|
||||
erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
const numDummyErc20ToDeploy = 3;
|
||||
[erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
|
||||
numDummyErc20ToDeploy,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
);
|
||||
erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
|
||||
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
||||
erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
||||
erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address];
|
||||
|
||||
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
assetDataUtils.encodeERC20AssetData(zrxToken.address),
|
||||
);
|
||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
maliciousWallet = maliciousValidator = await TestStaticCallReceiverContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestStaticCallReceiver,
|
||||
provider,
|
||||
@ -126,9 +122,72 @@ describe('Exchange core', () => {
|
||||
exchange.address,
|
||||
);
|
||||
|
||||
// Configure ERC20Proxy
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
// Configure ERC721Proxy
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
// Configure MultiAssetProxy
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
|
||||
from: owner,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
// Configure Exchange
|
||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
|
||||
|
||||
// Configure ERC20 tokens
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
|
||||
// Configure ERC721 tokens
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
||||
erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address];
|
||||
|
||||
// Configure order defaults
|
||||
defaultMakerAssetAddress = erc20TokenA.address;
|
||||
defaultTakerAssetAddress = erc20TokenB.address;
|
||||
|
||||
const defaultOrderParams = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
exchangeAddress: exchange.address,
|
||||
@ -707,6 +766,292 @@ describe('Exchange core', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing exchange of multiple assets', () => {
|
||||
it('should allow multiple assets to be exchanged for a single asset', async () => {
|
||||
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
|
||||
const makerNestedAssetData = [
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
|
||||
];
|
||||
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
|
||||
makerAmounts,
|
||||
makerNestedAssetData,
|
||||
);
|
||||
const makerAssetAmount = new BigNumber(1);
|
||||
const takerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
const takerAssetAmount = new BigNumber(10);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAssetAmount,
|
||||
takerAssetAmount,
|
||||
makerFee: constants.ZERO_AMOUNT,
|
||||
takerFee: constants.ZERO_AMOUNT,
|
||||
});
|
||||
|
||||
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
|
||||
|
||||
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
expect(finalMakerBalanceA).to.be.bignumber.equal(
|
||||
initialMakerBalanceA.minus(makerAmounts[0].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalMakerBalanceB).to.be.bignumber.equal(
|
||||
initialMakerBalanceB.minus(makerAmounts[1].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalMakerZrxBalance).to.be.bignumber.equal(initialMakerZrxBalance.plus(takerAssetAmount));
|
||||
expect(finalTakerBalanceA).to.be.bignumber.equal(
|
||||
initialTakerBalanceA.plus(makerAmounts[0].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalTakerBalanceB).to.be.bignumber.equal(
|
||||
initialTakerBalanceB.plus(makerAmounts[1].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalTakerZrxBalance).to.be.bignumber.equal(initialTakerZrxBalance.minus(takerAssetAmount));
|
||||
});
|
||||
it('should allow multiple assets to be exchanged for multiple assets', async () => {
|
||||
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
|
||||
const makerNestedAssetData = [
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
|
||||
];
|
||||
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
|
||||
makerAmounts,
|
||||
makerNestedAssetData,
|
||||
);
|
||||
const makerAssetAmount = new BigNumber(1);
|
||||
const takerAmounts = [new BigNumber(10), new BigNumber(1)];
|
||||
const takerAssetId = erc721TakerAssetIds[0];
|
||||
const takerNestedAssetData = [
|
||||
assetDataUtils.encodeERC20AssetData(zrxToken.address),
|
||||
assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
|
||||
];
|
||||
const takerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
|
||||
takerAmounts,
|
||||
takerNestedAssetData,
|
||||
);
|
||||
const takerAssetAmount = new BigNumber(1);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAssetAmount,
|
||||
takerAssetAmount,
|
||||
makerFee: constants.ZERO_AMOUNT,
|
||||
takerFee: constants.ZERO_AMOUNT,
|
||||
});
|
||||
|
||||
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
|
||||
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
|
||||
|
||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
|
||||
|
||||
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
const finalOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
|
||||
|
||||
expect(finalMakerBalanceA).to.be.bignumber.equal(
|
||||
initialMakerBalanceA.minus(makerAmounts[0].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalMakerBalanceB).to.be.bignumber.equal(
|
||||
initialMakerBalanceB.minus(makerAmounts[1].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalMakerZrxBalance).to.be.bignumber.equal(
|
||||
initialMakerZrxBalance.plus(takerAmounts[0].times(takerAssetAmount)),
|
||||
);
|
||||
expect(finalTakerBalanceA).to.be.bignumber.equal(
|
||||
initialTakerBalanceA.plus(makerAmounts[0].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalTakerBalanceB).to.be.bignumber.equal(
|
||||
initialTakerBalanceB.plus(makerAmounts[1].times(makerAssetAmount)),
|
||||
);
|
||||
expect(finalTakerZrxBalance).to.be.bignumber.equal(
|
||||
initialTakerZrxBalance.minus(takerAmounts[0].times(takerAssetAmount)),
|
||||
);
|
||||
expect(finalOwnerTakerAsset).to.be.equal(makerAddress);
|
||||
});
|
||||
it('should allow an order selling multiple assets to be partially filled', async () => {
|
||||
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
|
||||
const makerNestedAssetData = [
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
|
||||
];
|
||||
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
|
||||
makerAmounts,
|
||||
makerNestedAssetData,
|
||||
);
|
||||
const makerAssetAmount = new BigNumber(30);
|
||||
const takerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
const takerAssetAmount = new BigNumber(10);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAssetAmount,
|
||||
takerAssetAmount,
|
||||
makerFee: constants.ZERO_AMOUNT,
|
||||
takerFee: constants.ZERO_AMOUNT,
|
||||
});
|
||||
|
||||
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
const takerAssetFillAmount = takerAssetAmount.dividedToIntegerBy(2);
|
||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
|
||||
takerAssetFillAmount,
|
||||
});
|
||||
|
||||
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
expect(finalMakerBalanceA).to.be.bignumber.equal(
|
||||
initialMakerBalanceA.minus(
|
||||
makerAmounts[0].times(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalMakerBalanceB).to.be.bignumber.equal(
|
||||
initialMakerBalanceB.minus(
|
||||
makerAmounts[1].times(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalMakerZrxBalance).to.be.bignumber.equal(
|
||||
initialMakerZrxBalance.plus(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
);
|
||||
expect(finalTakerBalanceA).to.be.bignumber.equal(
|
||||
initialTakerBalanceA.plus(
|
||||
makerAmounts[0].times(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalTakerBalanceB).to.be.bignumber.equal(
|
||||
initialTakerBalanceB.plus(
|
||||
makerAmounts[1].times(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalTakerZrxBalance).to.be.bignumber.equal(
|
||||
initialTakerZrxBalance.minus(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
);
|
||||
});
|
||||
it('should allow an order buying multiple assets to be partially filled', async () => {
|
||||
const takerAmounts = [new BigNumber(10), new BigNumber(20)];
|
||||
const takerNestedAssetData = [
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
|
||||
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
|
||||
];
|
||||
const takerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
|
||||
takerAmounts,
|
||||
takerNestedAssetData,
|
||||
);
|
||||
const takerAssetAmount = new BigNumber(30);
|
||||
const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
const makerAssetAmount = new BigNumber(10);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAssetAmount,
|
||||
takerAssetAmount,
|
||||
makerFee: constants.ZERO_AMOUNT,
|
||||
takerFee: constants.ZERO_AMOUNT,
|
||||
});
|
||||
|
||||
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
const takerAssetFillAmount = takerAssetAmount.dividedToIntegerBy(2);
|
||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
|
||||
takerAssetFillAmount,
|
||||
});
|
||||
|
||||
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
|
||||
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
|
||||
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
|
||||
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
|
||||
|
||||
expect(finalMakerBalanceA).to.be.bignumber.equal(
|
||||
initialMakerBalanceA.plus(
|
||||
takerAmounts[0].times(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalMakerBalanceB).to.be.bignumber.equal(
|
||||
initialMakerBalanceB.plus(
|
||||
takerAmounts[1].times(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalMakerZrxBalance).to.be.bignumber.equal(
|
||||
initialMakerZrxBalance.minus(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
);
|
||||
expect(finalTakerBalanceA).to.be.bignumber.equal(
|
||||
initialTakerBalanceA.minus(
|
||||
takerAmounts[0].times(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalTakerBalanceB).to.be.bignumber.equal(
|
||||
initialTakerBalanceB.minus(
|
||||
takerAmounts[1].times(
|
||||
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(finalTakerZrxBalance).to.be.bignumber.equal(
|
||||
initialTakerZrxBalance.plus(
|
||||
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOrderInfo', () => {
|
||||
beforeEach(async () => {
|
||||
signedOrder = await orderFactory.newSignedOrderAsync();
|
@ -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 }),
|
||||
);
|
@ -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);
|
@ -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;
|
@ -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();
|
@ -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,
|
@ -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;
|
@ -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;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user