update tests
This commit is contained in:
parent
3f8639bd9c
commit
e954e9ca20
@ -94,7 +94,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
|
|||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
);
|
);
|
||||||
const exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
const exchangeWrapper = new ExchangeWrapper(exchange);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
|
||||||
|
@ -57,26 +57,12 @@ contract MixinExchangeWrapper is
|
|||||||
);
|
);
|
||||||
|
|
||||||
address exchange = address(EXCHANGE);
|
address exchange = address(EXCHANGE);
|
||||||
|
(bool didSucceed, bytes memory returnData) = exchange.call(fillOrderCalldata);
|
||||||
|
if (didSucceed) {
|
||||||
|
assert(returnData.length == 160);
|
||||||
|
fillResults = abi.decode(returnData, (LibFillResults.FillResults));
|
||||||
|
}
|
||||||
|
|
||||||
// Call `fillOrder` and handle any exceptions gracefully
|
|
||||||
assembly {
|
|
||||||
let success := call(
|
|
||||||
gas, // forward all gas
|
|
||||||
exchange, // call address of Exchange contract
|
|
||||||
0, // transfer 0 wei
|
|
||||||
add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)
|
|
||||||
mload(fillOrderCalldata), // length of input
|
|
||||||
fillOrderCalldata, // write output over input
|
|
||||||
160 // output size is 160 bytes
|
|
||||||
)
|
|
||||||
if success {
|
|
||||||
mstore(fillResults, mload(fillOrderCalldata))
|
|
||||||
mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))
|
|
||||||
mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))
|
|
||||||
mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))
|
|
||||||
mstore(add(fillResults, 128), mload(add(fillOrderCalldata, 128)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fillResults values will be 0 by default if call was unsuccessful
|
// fillResults values will be 0 by default if call was unsuccessful
|
||||||
return fillResults;
|
return fillResults;
|
||||||
}
|
}
|
||||||
@ -99,12 +85,14 @@ contract MixinExchangeWrapper is
|
|||||||
uint256 makerAssetAcquiredAmount
|
uint256 makerAssetAcquiredAmount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// No fee or percentage fee
|
uint256 protocolFee = tx.gasprice.safeMul(EXCHANGE.protocolFeeMultiplier());
|
||||||
|
|
||||||
|
// No taker fee or percentage fee
|
||||||
if (order.takerFee == 0 || order.takerFeeAssetData.equals(order.makerAssetData)) {
|
if (order.takerFee == 0 || order.takerFeeAssetData.equals(order.makerAssetData)) {
|
||||||
// Attempt to sell the remaining amount of WETH
|
// Attempt to sell the remaining amount of WETH
|
||||||
LibFillResults.FillResults memory singleFillResults = _fillOrderNoThrow(
|
LibFillResults.FillResults memory singleFillResults = _fillOrderNoThrow(
|
||||||
order,
|
order,
|
||||||
remainingTakerAssetFillAmount,
|
remainingTakerAssetFillAmount.safeSub(protocolFee),
|
||||||
signature
|
signature
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -118,14 +106,13 @@ contract MixinExchangeWrapper is
|
|||||||
);
|
);
|
||||||
// WETH fee
|
// WETH fee
|
||||||
} else if (order.takerFeeAssetData.equals(order.takerAssetData)) {
|
} else if (order.takerFeeAssetData.equals(order.takerAssetData)) {
|
||||||
uint256 protocolFee = tx.gasprice.safeMul(EXCHANGE.protocolFeeMultiplier());
|
|
||||||
|
|
||||||
// We will first sell WETH as the takerAsset, then use it to pay the takerFee.
|
// We will first sell WETH as the takerAsset, then use it to pay the takerFee.
|
||||||
// This ensures that we reserve enough to pay the fee.
|
// This ensures that we reserve enough to pay the taker and protocol fees.
|
||||||
uint256 takerAssetFillAmount = LibMath.getPartialAmountCeil(
|
uint256 takerAssetFillAmount = LibMath.getPartialAmountCeil(
|
||||||
order.takerAssetAmount,
|
order.takerAssetAmount,
|
||||||
order.takerAssetAmount.safeAdd(order.takerFee).safeAdd(protocolFee),
|
order.takerAssetAmount.safeAdd(order.takerFee),
|
||||||
remainingTakerAssetFillAmount
|
remainingTakerAssetFillAmount.safeSub(protocolFee)
|
||||||
);
|
);
|
||||||
|
|
||||||
LibFillResults.FillResults memory singleFillResults = _fillOrderNoThrow(
|
LibFillResults.FillResults memory singleFillResults = _fillOrderNoThrow(
|
||||||
@ -222,7 +209,7 @@ contract MixinExchangeWrapper is
|
|||||||
uint256 makerAssetAcquiredAmount
|
uint256 makerAssetAcquiredAmount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// No fee or WETH fee
|
// No taker fee or WETH fee
|
||||||
if (order.takerFee == 0 || order.takerFeeAssetData.equals(order.takerAssetData)) {
|
if (order.takerFee == 0 || order.takerFeeAssetData.equals(order.takerAssetData)) {
|
||||||
// Calculate the remaining amount of takerAsset to sell
|
// Calculate the remaining amount of takerAsset to sell
|
||||||
uint256 remainingTakerAssetFillAmount = LibMath.getPartialAmountCeil(
|
uint256 remainingTakerAssetFillAmount = LibMath.getPartialAmountCeil(
|
||||||
@ -238,7 +225,7 @@ contract MixinExchangeWrapper is
|
|||||||
signature
|
signature
|
||||||
);
|
);
|
||||||
|
|
||||||
// WETH is also spent on the taker fee, so we add it here.
|
// WETH is also spent on the protocol and taker fees, so we add it here.
|
||||||
wethSpentAmount = singleFillResults.takerAssetFilledAmount.safeAdd(
|
wethSpentAmount = singleFillResults.takerAssetFilledAmount.safeAdd(
|
||||||
singleFillResults.takerFeePaid
|
singleFillResults.takerFeePaid
|
||||||
).safeAdd(
|
).safeAdd(
|
||||||
|
@ -47,19 +47,19 @@ contract MixinWeth is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
if (msg.value == 0) {
|
if (msg.value == 0) {
|
||||||
LibRichErrors.rrevert(LibForwarderRichErrors.MsgValueCantEqualZeroError());
|
LibRichErrors.rrevert(LibForwarderRichErrors.MsgValueCannotEqualZeroError());
|
||||||
}
|
}
|
||||||
ETHER_TOKEN.deposit.value(msg.value)();
|
ETHER_TOKEN.deposit.value(msg.value)();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.
|
/// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.
|
||||||
/// Refunds any excess ETH to msg.sender.
|
/// Refunds any excess ETH to msg.sender.
|
||||||
/// @param wethSold Amount of WETH sold when filling primary orders.
|
/// @param wethSpent Amount of WETH spent when filling orders.
|
||||||
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
/// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.
|
||||||
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
/// @param feeRecipient Address that will receive ETH when orders are filled.
|
||||||
/// @return ethFee Amount paid to feeRecipient as a percentage fee on the total WETH sold.
|
/// @return ethFee Amount paid to feeRecipient as a percentage fee on the total WETH sold.
|
||||||
function _transferEthFeeAndRefund(
|
function _transferEthFeeAndRefund(
|
||||||
uint256 wethSold,
|
uint256 wethSpent,
|
||||||
uint256 feePercentage,
|
uint256 feePercentage,
|
||||||
address payable feeRecipient
|
address payable feeRecipient
|
||||||
)
|
)
|
||||||
@ -73,22 +73,22 @@ contract MixinWeth is
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that no extra WETH owned by this contract has been sold.
|
// Ensure that no extra WETH owned by this contract has been spent.
|
||||||
if (wethSold > msg.value) {
|
if (wethSpent > msg.value) {
|
||||||
LibRichErrors.rrevert(LibForwarderRichErrors.OversoldWethError(
|
LibRichErrors.rrevert(LibForwarderRichErrors.OverspentWethError(
|
||||||
wethSold,
|
wethSpent,
|
||||||
msg.value
|
msg.value
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate amount of WETH that hasn't been sold.
|
// Calculate amount of WETH that hasn't been spent.
|
||||||
uint256 wethRemaining = msg.value.safeSub(wethSold);
|
uint256 wethRemaining = msg.value.safeSub(wethSpent);
|
||||||
|
|
||||||
// Calculate ETH fee to pay to feeRecipient.
|
// Calculate ETH fee to pay to feeRecipient.
|
||||||
ethFee = LibMath.getPartialAmountFloor(
|
ethFee = LibMath.getPartialAmountFloor(
|
||||||
feePercentage,
|
feePercentage,
|
||||||
PERCENTAGE_DENOMINATOR,
|
PERCENTAGE_DENOMINATOR,
|
||||||
wethSold
|
wethSpent
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure fee is less than amount of WETH remaining.
|
// Ensure fee is less than amount of WETH remaining.
|
||||||
|
@ -21,7 +21,6 @@ pragma solidity ^0.5.9;
|
|||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
|
||||||
|
|
||||||
|
|
||||||
contract LibConstants {
|
contract LibConstants {
|
||||||
|
@ -51,9 +51,9 @@ library LibForwarderRichErrors {
|
|||||||
bytes4 internal constant INSUFFICIENT_ETH_FOR_FEE_ERROR_SELECTOR =
|
bytes4 internal constant INSUFFICIENT_ETH_FOR_FEE_ERROR_SELECTOR =
|
||||||
0xecf40fd9;
|
0xecf40fd9;
|
||||||
|
|
||||||
// bytes4(keccak256("OversoldWethError(uint256,uint256)"))
|
// bytes4(keccak256("OverspentWethError(uint256,uint256)"))
|
||||||
bytes4 internal constant OVERSOLD_WETH_ERROR_SELECTOR =
|
bytes4 internal constant OVERSPENT_WETH_ERROR_SELECTOR =
|
||||||
0x5cc555c8;
|
0xcdcbed5d;
|
||||||
|
|
||||||
// bytes4(keccak256("TransferFailedError(bytes)"))
|
// bytes4(keccak256("TransferFailedError(bytes)"))
|
||||||
bytes4 internal constant TRANSFER_FAILED_ERROR_SELECTOR =
|
bytes4 internal constant TRANSFER_FAILED_ERROR_SELECTOR =
|
||||||
@ -63,9 +63,9 @@ library LibForwarderRichErrors {
|
|||||||
bytes4 internal constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY_ERROR_SELECTOR =
|
bytes4 internal constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY_ERROR_SELECTOR =
|
||||||
0x08b18698;
|
0x08b18698;
|
||||||
|
|
||||||
// bytes4(keccak256("MsgValueCantEqualZeroError()"))
|
// bytes4(keccak256("MsgValueCannotEqualZeroError()"))
|
||||||
bytes4 internal constant MSG_VALUE_CANT_EQUAL_ZERO_ERROR_SELECTOR =
|
bytes4 internal constant MSG_VALUE_CANNOT_EQUAL_ZERO_ERROR_SELECTOR =
|
||||||
0x1213e1d6;
|
0x8c0e562b;
|
||||||
|
|
||||||
// bytes4(keccak256("Erc721AmountMustEqualOneError(uint256)"))
|
// bytes4(keccak256("Erc721AmountMustEqualOneError(uint256)"))
|
||||||
bytes4 internal constant ERC721_AMOUNT_MUST_EQUAL_ONE_ERROR_SELECTOR =
|
bytes4 internal constant ERC721_AMOUNT_MUST_EQUAL_ONE_ERROR_SELECTOR =
|
||||||
@ -164,8 +164,8 @@ library LibForwarderRichErrors {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function OversoldWethError(
|
function OverspentWethError(
|
||||||
uint256 wethSold,
|
uint256 wethSpent,
|
||||||
uint256 msgValue
|
uint256 msgValue
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
@ -173,8 +173,8 @@ library LibForwarderRichErrors {
|
|||||||
returns (bytes memory)
|
returns (bytes memory)
|
||||||
{
|
{
|
||||||
return abi.encodeWithSelector(
|
return abi.encodeWithSelector(
|
||||||
OVERSOLD_WETH_ERROR_SELECTOR,
|
OVERSPENT_WETH_ERROR_SELECTOR,
|
||||||
wethSold,
|
wethSpent,
|
||||||
msgValue
|
msgValue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -205,12 +205,12 @@ library LibForwarderRichErrors {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MsgValueCantEqualZeroError()
|
function MsgValueCannotEqualZeroError()
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (bytes memory)
|
returns (bytes memory)
|
||||||
{
|
{
|
||||||
return abi.encodeWithSelector(MSG_VALUE_CANT_EQUAL_ZERO_ERROR_SELECTOR);
|
return abi.encodeWithSelector(MSG_VALUE_CANNOT_EQUAL_ZERO_ERROR_SELECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Erc721AmountMustEqualOneError(
|
function Erc721AmountMustEqualOneError(
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 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.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
|
||||||
|
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable no-unused-vars
|
||||||
|
contract TestProtocolFeeCollector {
|
||||||
|
|
||||||
|
address private _wethAddress;
|
||||||
|
address private _wethAssetProxyAddress;
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
address wethAddress,
|
||||||
|
address wethAssetProxyAddress
|
||||||
|
)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_wethAddress = wethAddress;
|
||||||
|
_wethAssetProxyAddress = wethAssetProxyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Pays a protocol fee in WETH (Forwarder orders will always pay protocol fees in WETH).
|
||||||
|
/// @param makerAddress The address of the order's maker.
|
||||||
|
/// @param payerAddress The address of the protocol fee payer.
|
||||||
|
/// @param protocolFeePaid The protocol fee that should be paid.
|
||||||
|
function payProtocolFee(
|
||||||
|
address makerAddress,
|
||||||
|
address payerAddress,
|
||||||
|
uint256 protocolFeePaid
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
{
|
||||||
|
assert(msg.value == 0);
|
||||||
|
|
||||||
|
IAssetProxy wethAssetProxy = IAssetProxy(_wethAssetProxyAddress);
|
||||||
|
bytes memory wethAssetData = abi.encodeWithSelector(
|
||||||
|
IAssetData(address(0)).ERC20Token.selector,
|
||||||
|
_wethAddress
|
||||||
|
);
|
||||||
|
// Transfer the protocol fee to this address in WETH.
|
||||||
|
wethAssetProxy.transferFrom(
|
||||||
|
wethAssetData,
|
||||||
|
payerAddress,
|
||||||
|
address(this),
|
||||||
|
protocolFeePaid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn pre_build && tsc -b",
|
"build": "yarn pre_build && tsc -b",
|
||||||
|
"build:ts": "tsc -b",
|
||||||
"build:ci": "yarn build",
|
"build:ci": "yarn build",
|
||||||
"pre_build": "run-s compile contracts:gen generate_contract_wrappers",
|
"pre_build": "run-s compile contracts:gen generate_contract_wrappers",
|
||||||
"test": "yarn run_mocha",
|
"test": "yarn run_mocha",
|
||||||
@ -34,7 +35,7 @@
|
|||||||
"compile:truffle": "truffle compile"
|
"compile:truffle": "truffle compile"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./generated-artifacts/@(Forwarder|IAssets|IForwarder|IForwarderCore|LibConstants|LibForwarderRichErrors|MixinAssets|MixinExchangeWrapper|MixinForwarderCore|MixinWeth).json",
|
"abis": "./generated-artifacts/@(Forwarder|IAssets|IForwarder|IForwarderCore|LibConstants|LibForwarderRichErrors|MixinAssets|MixinExchangeWrapper|MixinForwarderCore|MixinWeth|TestProtocolFeeCollector).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -15,6 +15,7 @@ import * as MixinAssets from '../generated-artifacts/MixinAssets.json';
|
|||||||
import * as MixinExchangeWrapper from '../generated-artifacts/MixinExchangeWrapper.json';
|
import * as MixinExchangeWrapper from '../generated-artifacts/MixinExchangeWrapper.json';
|
||||||
import * as MixinForwarderCore from '../generated-artifacts/MixinForwarderCore.json';
|
import * as MixinForwarderCore from '../generated-artifacts/MixinForwarderCore.json';
|
||||||
import * as MixinWeth from '../generated-artifacts/MixinWeth.json';
|
import * as MixinWeth from '../generated-artifacts/MixinWeth.json';
|
||||||
|
import * as TestProtocolFeeCollector from '../generated-artifacts/TestProtocolFeeCollector.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
Forwarder: Forwarder as ContractArtifact,
|
Forwarder: Forwarder as ContractArtifact,
|
||||||
MixinAssets: MixinAssets as ContractArtifact,
|
MixinAssets: MixinAssets as ContractArtifact,
|
||||||
@ -26,4 +27,5 @@ export const artifacts = {
|
|||||||
IForwarderCore: IForwarderCore as ContractArtifact,
|
IForwarderCore: IForwarderCore as ContractArtifact,
|
||||||
LibConstants: LibConstants as ContractArtifact,
|
LibConstants: LibConstants as ContractArtifact,
|
||||||
LibForwarderRichErrors: LibForwarderRichErrors as ContractArtifact,
|
LibForwarderRichErrors: LibForwarderRichErrors as ContractArtifact,
|
||||||
|
TestProtocolFeeCollector: TestProtocolFeeCollector as ContractArtifact,
|
||||||
};
|
};
|
||||||
|
@ -13,3 +13,4 @@ export * from '../generated-wrappers/mixin_assets';
|
|||||||
export * from '../generated-wrappers/mixin_exchange_wrapper';
|
export * from '../generated-wrappers/mixin_exchange_wrapper';
|
||||||
export * from '../generated-wrappers/mixin_forwarder_core';
|
export * from '../generated-wrappers/mixin_forwarder_core';
|
||||||
export * from '../generated-wrappers/mixin_weth';
|
export * from '../generated-wrappers/mixin_weth';
|
||||||
|
export * from '../generated-wrappers/test_protocol_fee_collector';
|
||||||
|
@ -14,21 +14,24 @@ import {
|
|||||||
import { assetDataUtils, ForwarderRevertErrors } from '@0x/order-utils';
|
import { assetDataUtils, ForwarderRevertErrors } from '@0x/order-utils';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
|
||||||
|
|
||||||
import { artifacts, ForwarderContract, ForwarderTestFactory, ForwarderWrapper } from '../src';
|
import {
|
||||||
|
artifacts,
|
||||||
|
ForwarderContract,
|
||||||
|
ForwarderTestFactory,
|
||||||
|
ForwarderWrapper,
|
||||||
|
TestProtocolFeeCollectorContract,
|
||||||
|
} from '../src';
|
||||||
|
|
||||||
const DECIMALS_DEFAULT = 18;
|
const DECIMALS_DEFAULT = 18;
|
||||||
|
|
||||||
blockchainTests(ContractName.Forwarder, env => {
|
blockchainTests(ContractName.Forwarder, env => {
|
||||||
let chainId: number;
|
|
||||||
let makerAddress: string;
|
|
||||||
let owner: string;
|
let owner: string;
|
||||||
|
let makerAddress: string;
|
||||||
let takerAddress: string;
|
let takerAddress: string;
|
||||||
let orderFeeRecipientAddress: string;
|
let orderFeeRecipientAddress: string;
|
||||||
let forwarderFeeRecipientAddress: string;
|
let forwarderFeeRecipientAddress: string;
|
||||||
let defaultMakerAssetAddress: string;
|
let defaultMakerAssetAddress: string;
|
||||||
let wethAssetData: string;
|
|
||||||
|
|
||||||
let weth: DummyERC20TokenContract;
|
let weth: DummyERC20TokenContract;
|
||||||
let erc20Token: DummyERC20TokenContract;
|
let erc20Token: DummyERC20TokenContract;
|
||||||
@ -36,22 +39,26 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
let erc721Token: DummyERC721TokenContract;
|
let erc721Token: DummyERC721TokenContract;
|
||||||
let forwarderContract: ForwarderContract;
|
let forwarderContract: ForwarderContract;
|
||||||
let wethContract: WETH9Contract;
|
let wethContract: WETH9Contract;
|
||||||
|
let exchangeContract: ExchangeContract;
|
||||||
|
let protocolFeeCollector: TestProtocolFeeCollectorContract;
|
||||||
|
|
||||||
let forwarderWrapper: ForwarderWrapper;
|
let forwarderWrapper: ForwarderWrapper;
|
||||||
let exchangeWrapper: ExchangeWrapper;
|
let exchangeWrapper: ExchangeWrapper;
|
||||||
|
let erc20Wrapper: ERC20Wrapper;
|
||||||
|
|
||||||
let orderFactory: OrderFactory;
|
let orderFactory: OrderFactory;
|
||||||
let forwarderTestFactory: ForwarderTestFactory;
|
let forwarderTestFactory: ForwarderTestFactory;
|
||||||
let erc20Wrapper: ERC20Wrapper;
|
|
||||||
let tx: TransactionReceiptWithDecodedLogs;
|
|
||||||
|
|
||||||
|
let chainId: number;
|
||||||
|
let wethAssetData: string;
|
||||||
let erc721MakerAssetIds: BigNumber[];
|
let erc721MakerAssetIds: BigNumber[];
|
||||||
const gasPrice = new BigNumber(constants.DEFAULT_GAS_PRICE);
|
|
||||||
|
const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE);
|
||||||
|
const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150);
|
||||||
|
const PROTOCOL_FEE = GAS_PRICE.times(PROTOCOL_FEE_MULTIPLIER);
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await env.blockchainLifecycle.startAsync();
|
// Set up addresses
|
||||||
|
|
||||||
chainId = await env.getChainIdAsync();
|
|
||||||
|
|
||||||
const accounts = await env.getAccountAddressesAsync();
|
const accounts = await env.getAccountAddressesAsync();
|
||||||
const usedAddresses = ([
|
const usedAddresses = ([
|
||||||
owner,
|
owner,
|
||||||
@ -61,24 +68,27 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
forwarderFeeRecipientAddress,
|
forwarderFeeRecipientAddress,
|
||||||
] = accounts);
|
] = accounts);
|
||||||
|
|
||||||
const erc721Wrapper = new ERC721Wrapper(env.provider, usedAddresses, owner);
|
// Set up Exchange
|
||||||
erc20Wrapper = new ERC20Wrapper(env.provider, usedAddresses, owner);
|
chainId = await env.getChainIdAsync();
|
||||||
|
exchangeContract = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
const numDummyErc20ToDeploy = 2;
|
exchangeArtifacts.Exchange,
|
||||||
[erc20Token, secondErc20Token] = await erc20Wrapper.deployDummyTokensAsync(
|
env.provider,
|
||||||
numDummyErc20ToDeploy,
|
env.txDefaults,
|
||||||
constants.DUMMY_TOKEN_DECIMALS,
|
{},
|
||||||
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
|
exchangeWrapper = new ExchangeWrapper(exchangeContract);
|
||||||
|
|
||||||
|
// Set up ERC20
|
||||||
|
erc20Wrapper = new ERC20Wrapper(env.provider, usedAddresses, owner);
|
||||||
|
[erc20Token, secondErc20Token] = await erc20Wrapper.deployDummyTokensAsync(2, constants.DUMMY_TOKEN_DECIMALS);
|
||||||
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
|
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeContract.address, {
|
||||||
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
from: owner,
|
||||||
const erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
});
|
||||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
|
||||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
|
||||||
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
|
||||||
|
|
||||||
|
// Set up WETH
|
||||||
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(
|
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||||
erc20Artifacts.WETH9,
|
erc20Artifacts.WETH9,
|
||||||
env.provider,
|
env.provider,
|
||||||
@ -86,59 +96,68 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
weth = new DummyERC20TokenContract(wethContract.address, env.provider);
|
weth = new DummyERC20TokenContract(wethContract.address, env.provider);
|
||||||
erc20Wrapper.addDummyTokenContract(weth);
|
|
||||||
|
|
||||||
wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
|
wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
|
||||||
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
erc20Wrapper.addDummyTokenContract(weth);
|
||||||
exchangeArtifacts.Exchange,
|
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||||
|
|
||||||
|
// Set up ERC721
|
||||||
|
const erc721Wrapper = new ERC721Wrapper(env.provider, usedAddresses, owner);
|
||||||
|
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
||||||
|
const erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||||
|
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||||
|
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||||
|
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
||||||
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
|
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeContract.address, {
|
||||||
|
from: owner,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up Protocol Fee Collector
|
||||||
|
protocolFeeCollector = await TestProtocolFeeCollectorContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestProtocolFeeCollector,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
{},
|
{},
|
||||||
new BigNumber(chainId),
|
wethContract.address,
|
||||||
|
erc20Proxy.address,
|
||||||
);
|
);
|
||||||
exchangeWrapper = new ExchangeWrapper(exchangeInstance, env.provider);
|
await exchangeContract.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(PROTOCOL_FEE_MULTIPLIER);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeContract.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
protocolFeeCollector.address,
|
||||||
|
);
|
||||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(protocolFeeCollector.address, {
|
||||||
from: owner,
|
|
||||||
});
|
|
||||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set defaults
|
||||||
defaultMakerAssetAddress = erc20Token.address;
|
defaultMakerAssetAddress = erc20Token.address;
|
||||||
const defaultTakerAssetAddress = wethContract.address;
|
|
||||||
const defaultOrderParams = {
|
const defaultOrderParams = {
|
||||||
makerAddress,
|
makerAddress,
|
||||||
feeRecipientAddress: orderFeeRecipientAddress,
|
feeRecipientAddress: orderFeeRecipientAddress,
|
||||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
|
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(200, DECIMALS_DEFAULT),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(200, DECIMALS_DEFAULT),
|
||||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, DECIMALS_DEFAULT),
|
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, DECIMALS_DEFAULT),
|
||||||
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
makerFee: Web3Wrapper.toBaseUnitAmount(0, DECIMALS_DEFAULT),
|
makerFee: Web3Wrapper.toBaseUnitAmount(0, DECIMALS_DEFAULT),
|
||||||
takerFee: Web3Wrapper.toBaseUnitAmount(0, DECIMALS_DEFAULT),
|
takerFee: Web3Wrapper.toBaseUnitAmount(0, DECIMALS_DEFAULT),
|
||||||
exchangeAddress: exchangeInstance.address,
|
exchangeAddress: exchangeContract.address,
|
||||||
chainId,
|
chainId,
|
||||||
};
|
};
|
||||||
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
|
||||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
|
||||||
|
|
||||||
|
// Set up Forwarder
|
||||||
forwarderContract = await ForwarderContract.deployFrom0xArtifactAsync(
|
forwarderContract = await ForwarderContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.Forwarder,
|
artifacts.Forwarder,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
{},
|
{},
|
||||||
exchangeInstance.address,
|
exchangeContract.address,
|
||||||
wethAssetData,
|
wethAssetData,
|
||||||
);
|
);
|
||||||
forwarderWrapper = new ForwarderWrapper(forwarderContract, env.provider);
|
forwarderWrapper = new ForwarderWrapper(forwarderContract, env.provider);
|
||||||
|
|
||||||
await forwarderWrapper.approveMakerAssetProxyAsync(defaultOrderParams.makerAssetData, { from: takerAddress });
|
await forwarderWrapper.approveMakerAssetProxyAsync(defaultOrderParams.makerAssetData, { from: takerAddress });
|
||||||
erc20Wrapper.addTokenOwnerAddress(forwarderContract.address);
|
erc20Wrapper.addTokenOwnerAddress(forwarderContract.address);
|
||||||
|
|
||||||
|
// Set up factories
|
||||||
|
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
||||||
|
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||||
forwarderTestFactory = new ForwarderTestFactory(
|
forwarderTestFactory = new ForwarderTestFactory(
|
||||||
exchangeWrapper,
|
exchangeWrapper,
|
||||||
forwarderWrapper,
|
forwarderWrapper,
|
||||||
@ -146,16 +165,18 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
forwarderContract.address,
|
forwarderContract.address,
|
||||||
makerAddress,
|
makerAddress,
|
||||||
takerAddress,
|
takerAddress,
|
||||||
|
protocolFeeCollector.address,
|
||||||
orderFeeRecipientAddress,
|
orderFeeRecipientAddress,
|
||||||
forwarderFeeRecipientAddress,
|
forwarderFeeRecipientAddress,
|
||||||
weth.address,
|
weth.address,
|
||||||
gasPrice,
|
GAS_PRICE,
|
||||||
|
PROTOCOL_FEE_MULTIPLIER,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
blockchainTests.resets('constructor', () => {
|
blockchainTests.resets('constructor', () => {
|
||||||
it('should revert if assetProxy is unregistered', async () => {
|
it('should revert if assetProxy is unregistered', async () => {
|
||||||
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
|
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
exchangeArtifacts.Exchange,
|
exchangeArtifacts.Exchange,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
@ -168,7 +189,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
{},
|
{},
|
||||||
exchangeInstance.address,
|
exchange.address,
|
||||||
wethAssetData,
|
wethAssetData,
|
||||||
) as any) as sendTransactionResult;
|
) as any) as sendTransactionResult;
|
||||||
|
|
||||||
@ -223,7 +244,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
|
|
||||||
// Execute test case
|
// Execute test case
|
||||||
tx = await forwarderWrapper.marketSellOrdersWithEthAsync([order], {
|
const tx = await forwarderWrapper.marketSellOrdersWithEthAsync([order], {
|
||||||
value: ethValue,
|
value: ethValue,
|
||||||
from: takerAddress,
|
from: takerAddress,
|
||||||
});
|
});
|
||||||
@ -231,7 +252,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
const totalEthSpent = gasPrice.times(tx.gasUsed);
|
const totalEthSpent = GAS_PRICE.times(tx.gasUsed);
|
||||||
|
|
||||||
// Validate test case
|
// Validate test case
|
||||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||||
@ -273,15 +294,15 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
});
|
});
|
||||||
it('should refund remaining ETH if amount is greater than takerAssetAmount', async () => {
|
it('should refund remaining ETH if amount is greater than takerAssetAmount', async () => {
|
||||||
const order = await orderFactory.newSignedOrderAsync();
|
const order = await orderFactory.newSignedOrderAsync();
|
||||||
const ethValue = order.takerAssetAmount.plus(2);
|
const ethValue = order.takerAssetAmount.plus(PROTOCOL_FEE).plus(2);
|
||||||
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
|
|
||||||
tx = await forwarderWrapper.marketSellOrdersWithEthAsync([order], {
|
const tx = await forwarderWrapper.marketSellOrdersWithEthAsync([order], {
|
||||||
value: ethValue,
|
value: ethValue,
|
||||||
from: takerAddress,
|
from: takerAddress,
|
||||||
});
|
});
|
||||||
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
const totalEthSpent = order.takerAssetAmount.plus(gasPrice.times(tx.gasUsed));
|
const totalEthSpent = order.takerAssetAmount.plus(PROTOCOL_FEE).plus(GAS_PRICE.times(tx.gasUsed));
|
||||||
|
|
||||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||||
});
|
});
|
||||||
@ -527,7 +548,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const fillableOrder = await orderFactory.newSignedOrderAsync();
|
const fillableOrder = await orderFactory.newSignedOrderAsync();
|
||||||
await forwarderTestFactory.marketBuyTestAsync([cancelledOrder, fillableOrder], 1.5, erc20Token);
|
await forwarderTestFactory.marketBuyTestAsync([cancelledOrder, fillableOrder], 1.5, erc20Token);
|
||||||
});
|
});
|
||||||
it('Should buy slightly greater MakerAsset when exchange rate is rounded', async () => {
|
it('Should buy slightly greater makerAsset when exchange rate is rounded', async () => {
|
||||||
// The 0x Protocol contracts round the exchange rate in favor of the Maker.
|
// The 0x Protocol contracts round the exchange rate in favor of the Maker.
|
||||||
// In this case, the taker must round up how much they're going to spend, which
|
// In this case, the taker must round up how much they're going to spend, which
|
||||||
// in turn increases the amount of MakerAsset being purchased.
|
// in turn increases the amount of MakerAsset being purchased.
|
||||||
@ -553,13 +574,14 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
});
|
});
|
||||||
const desiredMakerAssetFillAmount = new BigNumber('5');
|
const desiredMakerAssetFillAmount = new BigNumber('5');
|
||||||
const makerAssetFillAmount = new BigNumber('6');
|
const makerAssetFillAmount = new BigNumber('6');
|
||||||
const ethValue = new BigNumber('4');
|
const primaryTakerAssetFillAmount = new BigNumber('4');
|
||||||
|
const ethValue = primaryTakerAssetFillAmount.plus(PROTOCOL_FEE);
|
||||||
|
|
||||||
const erc20Balances = await erc20Wrapper.getBalancesAsync();
|
const erc20Balances = await erc20Wrapper.getBalancesAsync();
|
||||||
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
|
|
||||||
// Execute test case
|
// Execute test case
|
||||||
tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([order], desiredMakerAssetFillAmount, {
|
const tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([order], desiredMakerAssetFillAmount, {
|
||||||
value: ethValue,
|
value: ethValue,
|
||||||
from: takerAddress,
|
from: takerAddress,
|
||||||
});
|
});
|
||||||
@ -567,8 +589,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
const takerEthBalanceAfter = await env.web3Wrapper.getBalanceInWeiAsync(takerAddress);
|
||||||
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
const primaryTakerAssetFillAmount = ethValue;
|
const totalEthSpent = ethValue.plus(GAS_PRICE.times(tx.gasUsed));
|
||||||
const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
|
|
||||||
// Validate test case
|
// Validate test case
|
||||||
expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
|
expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
|
||||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||||
@ -588,6 +609,8 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
it('Should buy slightly greater MakerAsset when exchange rate is rounded (Regression Test)', async () => {
|
it('Should buy slightly greater MakerAsset when exchange rate is rounded (Regression Test)', async () => {
|
||||||
|
// Disable protocol fees for regression test
|
||||||
|
await exchangeContract.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(constants.NULL_ADDRESS);
|
||||||
// Order taken from a transaction on mainnet that failed due to a rounding error.
|
// Order taken from a transaction on mainnet that failed due to a rounding error.
|
||||||
const order = await orderFactory.newSignedOrderAsync({
|
const order = await orderFactory.newSignedOrderAsync({
|
||||||
makerAssetAmount: new BigNumber('268166666666666666666'),
|
makerAssetAmount: new BigNumber('268166666666666666666'),
|
||||||
@ -608,7 +631,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
.times(order.makerAssetAmount)
|
.times(order.makerAssetAmount)
|
||||||
.dividedToIntegerBy(order.takerAssetAmount);
|
.dividedToIntegerBy(order.takerAssetAmount);
|
||||||
// Execute test case
|
// Execute test case
|
||||||
tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([order], desiredMakerAssetFillAmount, {
|
const tx = await forwarderWrapper.marketBuyOrdersWithEthAsync([order], desiredMakerAssetFillAmount, {
|
||||||
value: ethValue,
|
value: ethValue,
|
||||||
from: takerAddress,
|
from: takerAddress,
|
||||||
});
|
});
|
||||||
@ -617,7 +640,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
const forwarderEthBalance = await env.web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
const primaryTakerAssetFillAmount = ethValue;
|
const primaryTakerAssetFillAmount = ethValue;
|
||||||
const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
|
const totalEthSpent = primaryTakerAssetFillAmount.plus(GAS_PRICE.times(tx.gasUsed));
|
||||||
// Validate test case
|
// Validate test case
|
||||||
expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
|
expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
|
||||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||||
@ -661,7 +684,7 @@ blockchainTests(ContractName.Forwarder, env => {
|
|||||||
const order = await orderFactory.newSignedOrderAsync();
|
const order = await orderFactory.newSignedOrderAsync();
|
||||||
const forwarderFeePercentage = new BigNumber(2);
|
const forwarderFeePercentage = new BigNumber(2);
|
||||||
const ethFee = ForwarderTestFactory.getPercentageOfValue(
|
const ethFee = ForwarderTestFactory.getPercentageOfValue(
|
||||||
order.takerAssetAmount.times(0.5),
|
order.takerAssetAmount.times(0.5).plus(PROTOCOL_FEE),
|
||||||
forwarderFeePercentage,
|
forwarderFeePercentage,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,118 +2,31 @@ import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
|
|||||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||||
import { ExchangeWrapper } from '@0x/contracts-exchange';
|
import { ExchangeWrapper } from '@0x/contracts-exchange';
|
||||||
import { chaiSetup, constants, ERC20BalancesByOwner, OrderStatus, web3Wrapper } from '@0x/contracts-test-utils';
|
import { constants, ERC20BalancesByOwner, expect, OrderStatus, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
import { OrderInfo, SignedOrder } from '@0x/types';
|
import { OrderInfo, SignedOrder } from '@0x/types';
|
||||||
import { BigNumber, RevertError } from '@0x/utils';
|
import { BigNumber, RevertError } from '@0x/utils';
|
||||||
import * as chai from 'chai';
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ForwarderWrapper } from './forwarder_wrapper';
|
import { ForwarderWrapper } from './forwarder_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
|
||||||
const expect = chai.expect;
|
|
||||||
|
|
||||||
// Necessary bookkeeping to validate Forwarder results
|
// Necessary bookkeeping to validate Forwarder results
|
||||||
interface ForwarderFillState {
|
interface ForwarderFillState {
|
||||||
takerAssetFillAmount: BigNumber;
|
takerAssetFillAmount: BigNumber;
|
||||||
makerAssetFillAmount: BigNumber;
|
makerAssetFillAmount: BigNumber;
|
||||||
|
protocolFees: BigNumber;
|
||||||
wethFees: BigNumber;
|
wethFees: BigNumber;
|
||||||
percentageFees: BigNumber;
|
percentageFees: BigNumber;
|
||||||
maxOversoldWeth: BigNumber;
|
maxOversoldWeth: BigNumber;
|
||||||
maxOverboughtMakerAsset: BigNumber;
|
maxOverboughtMakerAsset: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulates filling some orders via the Forwarder contract. For example, if
|
|
||||||
// orders = [A, B, C, D] and fractionalNumberOfOrdersToFill = 2.3, then
|
|
||||||
// we simulate A and B being completely filled, and 0.3 * C being filled.
|
|
||||||
function computeExpectedResults(
|
|
||||||
orders: SignedOrder[],
|
|
||||||
ordersInfoBefore: OrderInfo[],
|
|
||||||
fractionalNumberOfOrdersToFill: number,
|
|
||||||
): ForwarderFillState {
|
|
||||||
const currentState = {
|
|
||||||
takerAssetFillAmount: constants.ZERO_AMOUNT,
|
|
||||||
makerAssetFillAmount: constants.ZERO_AMOUNT,
|
|
||||||
wethFees: constants.ZERO_AMOUNT,
|
|
||||||
percentageFees: constants.ZERO_AMOUNT,
|
|
||||||
maxOversoldWeth: constants.ZERO_AMOUNT,
|
|
||||||
maxOverboughtMakerAsset: constants.ZERO_AMOUNT,
|
|
||||||
};
|
|
||||||
let remainingOrdersToFill = fractionalNumberOfOrdersToFill;
|
|
||||||
|
|
||||||
for (const [i, order] of orders.entries()) {
|
|
||||||
if (remainingOrdersToFill === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ordersInfoBefore[i].orderStatus !== OrderStatus.Fillable) {
|
|
||||||
// If the order is not fillable, skip over it but still count it towards fractionalNumberOfOrdersToFill
|
|
||||||
remainingOrdersToFill = Math.max(remainingOrdersToFill - 1, 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let makerAssetAmount;
|
|
||||||
let takerAssetAmount;
|
|
||||||
let takerFee;
|
|
||||||
if (remainingOrdersToFill < 1) {
|
|
||||||
makerAssetAmount = order.makerAssetAmount.times(remainingOrdersToFill).integerValue();
|
|
||||||
takerAssetAmount = order.takerAssetAmount.times(remainingOrdersToFill).integerValue();
|
|
||||||
takerFee = order.takerFee.times(remainingOrdersToFill).integerValue();
|
|
||||||
|
|
||||||
// Up to 1 wei worth of WETH will be oversold on the last order due to rounding
|
|
||||||
currentState.maxOversoldWeth = new BigNumber(1);
|
|
||||||
// Equivalently, up to 1 wei worth of maker asset will be overbought
|
|
||||||
currentState.maxOverboughtMakerAsset = currentState.maxOversoldWeth
|
|
||||||
.times(order.makerAssetAmount)
|
|
||||||
.dividedToIntegerBy(order.takerAssetAmount);
|
|
||||||
} else {
|
|
||||||
makerAssetAmount = order.makerAssetAmount;
|
|
||||||
takerAssetAmount = order.takerAssetAmount;
|
|
||||||
takerFee = order.takerFee;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accounting for partially filled orders
|
|
||||||
// As with unfillable orders, these still count as 1 towards fractionalNumberOfOrdersToFill
|
|
||||||
const takerAssetFilled = ordersInfoBefore[i].orderTakerAssetFilledAmount;
|
|
||||||
const makerAssetFilled = takerAssetFilled
|
|
||||||
.times(order.makerAssetAmount)
|
|
||||||
.dividedToIntegerBy(order.takerAssetAmount);
|
|
||||||
takerAssetAmount = BigNumber.max(takerAssetAmount.minus(takerAssetFilled), constants.ZERO_AMOUNT);
|
|
||||||
makerAssetAmount = BigNumber.max(makerAssetAmount.minus(makerAssetFilled), constants.ZERO_AMOUNT);
|
|
||||||
|
|
||||||
currentState.takerAssetFillAmount = currentState.takerAssetFillAmount.plus(takerAssetAmount);
|
|
||||||
currentState.makerAssetFillAmount = currentState.makerAssetFillAmount.plus(makerAssetAmount);
|
|
||||||
|
|
||||||
if (order.takerFeeAssetData === order.makerAssetData) {
|
|
||||||
currentState.percentageFees = currentState.percentageFees.plus(takerFee);
|
|
||||||
} else if (order.takerFeeAssetData === order.takerAssetData) {
|
|
||||||
currentState.wethFees = currentState.wethFees.plus(takerFee);
|
|
||||||
}
|
|
||||||
|
|
||||||
remainingOrdersToFill = Math.max(remainingOrdersToFill - 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentState;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since bignumber is not compatible with chai's within
|
// Since bignumber is not compatible with chai's within
|
||||||
function expectBalanceWithin(balance: BigNumber, low: BigNumber, high: BigNumber): void {
|
function expectBalanceWithin(balance: BigNumber, low: BigNumber, high: BigNumber, message?: string): void {
|
||||||
expect(balance).to.be.bignumber.gte(low);
|
expect(balance, message).to.be.bignumber.gte(low);
|
||||||
expect(balance).to.be.bignumber.lte(high);
|
expect(balance, message).to.be.bignumber.lte(high);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ForwarderTestFactory {
|
export class ForwarderTestFactory {
|
||||||
private readonly _exchangeWrapper: ExchangeWrapper;
|
|
||||||
private readonly _forwarderWrapper: ForwarderWrapper;
|
|
||||||
private readonly _erc20Wrapper: ERC20Wrapper;
|
|
||||||
private readonly _forwarderAddress: string;
|
|
||||||
private readonly _makerAddress: string;
|
|
||||||
private readonly _takerAddress: string;
|
|
||||||
private readonly _orderFeeRecipientAddress: string;
|
|
||||||
private readonly _forwarderFeeRecipientAddress: string;
|
|
||||||
private readonly _wethAddress: string;
|
|
||||||
private readonly _gasPrice: BigNumber;
|
|
||||||
|
|
||||||
public static getPercentageOfValue(value: BigNumber, percentage: BigNumber): BigNumber {
|
public static getPercentageOfValue(value: BigNumber, percentage: BigNumber): BigNumber {
|
||||||
const numerator = constants.PERCENTAGE_DENOMINATOR.times(percentage).dividedToIntegerBy(100);
|
const numerator = constants.PERCENTAGE_DENOMINATOR.times(percentage).dividedToIntegerBy(100);
|
||||||
const newValue = value.times(numerator).dividedToIntegerBy(constants.PERCENTAGE_DENOMINATOR);
|
const newValue = value.times(numerator).dividedToIntegerBy(constants.PERCENTAGE_DENOMINATOR);
|
||||||
@ -121,28 +34,19 @@ export class ForwarderTestFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
exchangeWrapper: ExchangeWrapper,
|
private readonly _exchangeWrapper: ExchangeWrapper,
|
||||||
forwarderWrapper: ForwarderWrapper,
|
private readonly _forwarderWrapper: ForwarderWrapper,
|
||||||
erc20Wrapper: ERC20Wrapper,
|
private readonly _erc20Wrapper: ERC20Wrapper,
|
||||||
forwarderAddress: string,
|
private readonly _forwarderAddress: string,
|
||||||
makerAddress: string,
|
private readonly _makerAddress: string,
|
||||||
takerAddress: string,
|
private readonly _takerAddress: string,
|
||||||
orderFeeRecipientAddress: string,
|
private readonly _protocolFeeCollectorAddress: string,
|
||||||
forwarderFeeRecipientAddress: string,
|
private readonly _orderFeeRecipientAddress: string,
|
||||||
wethAddress: string,
|
private readonly _forwarderFeeRecipientAddress: string,
|
||||||
gasPrice: BigNumber,
|
private readonly _wethAddress: string,
|
||||||
) {
|
private readonly _gasPrice: BigNumber,
|
||||||
this._exchangeWrapper = exchangeWrapper;
|
private readonly _protocolFeeMultiplier: BigNumber,
|
||||||
this._forwarderWrapper = forwarderWrapper;
|
) {}
|
||||||
this._erc20Wrapper = erc20Wrapper;
|
|
||||||
this._forwarderAddress = forwarderAddress;
|
|
||||||
this._makerAddress = makerAddress;
|
|
||||||
this._takerAddress = takerAddress;
|
|
||||||
this._orderFeeRecipientAddress = orderFeeRecipientAddress;
|
|
||||||
this._forwarderFeeRecipientAddress = forwarderFeeRecipientAddress;
|
|
||||||
this._wethAddress = wethAddress;
|
|
||||||
this._gasPrice = gasPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async marketBuyTestAsync(
|
public async marketBuyTestAsync(
|
||||||
orders: SignedOrder[],
|
orders: SignedOrder[],
|
||||||
@ -167,22 +71,18 @@ export class ForwarderTestFactory {
|
|||||||
const ordersInfoBefore = await Promise.all(orders.map(order => this._exchangeWrapper.getOrderInfoAsync(order)));
|
const ordersInfoBefore = await Promise.all(orders.map(order => this._exchangeWrapper.getOrderInfoAsync(order)));
|
||||||
const orderStatusesBefore = ordersInfoBefore.map(orderInfo => orderInfo.orderStatus);
|
const orderStatusesBefore = ordersInfoBefore.map(orderInfo => orderInfo.orderStatus);
|
||||||
|
|
||||||
const expectedResults = computeExpectedResults(orders, ordersInfoBefore, fractionalNumberOfOrdersToFill);
|
const expectedResults = this._computeExpectedResults(orders, ordersInfoBefore, fractionalNumberOfOrdersToFill);
|
||||||
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(
|
const wethSpent = expectedResults.takerAssetFillAmount
|
||||||
expectedResults.takerAssetFillAmount,
|
.plus(expectedResults.protocolFees)
|
||||||
forwarderFeePercentage,
|
.plus(expectedResults.wethFees)
|
||||||
);
|
.plus(expectedResults.maxOversoldWeth);
|
||||||
|
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(wethSpent, forwarderFeePercentage);
|
||||||
|
const ethValue = wethSpent.plus(ethSpentOnForwarderFee).plus(ethValueAdjustment);
|
||||||
|
|
||||||
const feePercentage = ForwarderTestFactory.getPercentageOfValue(
|
const feePercentage = ForwarderTestFactory.getPercentageOfValue(
|
||||||
constants.PERCENTAGE_DENOMINATOR,
|
constants.PERCENTAGE_DENOMINATOR,
|
||||||
forwarderFeePercentage,
|
forwarderFeePercentage,
|
||||||
);
|
);
|
||||||
|
|
||||||
const ethValue = expectedResults.takerAssetFillAmount
|
|
||||||
.plus(expectedResults.wethFees)
|
|
||||||
.plus(expectedResults.maxOversoldWeth)
|
|
||||||
.plus(ethSpentOnForwarderFee)
|
|
||||||
.plus(ethValueAdjustment);
|
|
||||||
|
|
||||||
const tx = this._forwarderWrapper.marketBuyOrdersWithEthAsync(
|
const tx = this._forwarderWrapper.marketBuyOrdersWithEthAsync(
|
||||||
orders,
|
orders,
|
||||||
expectedResults.makerAssetFillAmount.minus(expectedResults.percentageFees),
|
expectedResults.makerAssetFillAmount.minus(expectedResults.percentageFees),
|
||||||
@ -240,21 +140,20 @@ export class ForwarderTestFactory {
|
|||||||
const ordersInfoBefore = await Promise.all(orders.map(order => this._exchangeWrapper.getOrderInfoAsync(order)));
|
const ordersInfoBefore = await Promise.all(orders.map(order => this._exchangeWrapper.getOrderInfoAsync(order)));
|
||||||
const orderStatusesBefore = ordersInfoBefore.map(orderInfo => orderInfo.orderStatus);
|
const orderStatusesBefore = ordersInfoBefore.map(orderInfo => orderInfo.orderStatus);
|
||||||
|
|
||||||
const expectedResults = computeExpectedResults(orders, ordersInfoBefore, fractionalNumberOfOrdersToFill);
|
const expectedResults = this._computeExpectedResults(orders, ordersInfoBefore, fractionalNumberOfOrdersToFill);
|
||||||
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(
|
const wethSpent = expectedResults.takerAssetFillAmount
|
||||||
expectedResults.takerAssetFillAmount,
|
.plus(expectedResults.protocolFees)
|
||||||
forwarderFeePercentage,
|
.plus(expectedResults.wethFees)
|
||||||
);
|
.plus(expectedResults.maxOversoldWeth);
|
||||||
|
|
||||||
|
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(wethSpent, forwarderFeePercentage);
|
||||||
|
const ethValue = wethSpent.plus(ethSpentOnForwarderFee);
|
||||||
|
|
||||||
const feePercentage = ForwarderTestFactory.getPercentageOfValue(
|
const feePercentage = ForwarderTestFactory.getPercentageOfValue(
|
||||||
constants.PERCENTAGE_DENOMINATOR,
|
constants.PERCENTAGE_DENOMINATOR,
|
||||||
forwarderFeePercentage,
|
forwarderFeePercentage,
|
||||||
);
|
);
|
||||||
|
|
||||||
const ethValue = expectedResults.takerAssetFillAmount
|
|
||||||
.plus(expectedResults.wethFees)
|
|
||||||
.plus(expectedResults.maxOversoldWeth)
|
|
||||||
.plus(ethSpentOnForwarderFee);
|
|
||||||
|
|
||||||
const tx = this._forwarderWrapper.marketSellOrdersWithEthAsync(
|
const tx = this._forwarderWrapper.marketSellOrdersWithEthAsync(
|
||||||
orders,
|
orders,
|
||||||
{
|
{
|
||||||
@ -268,10 +167,9 @@ export class ForwarderTestFactory {
|
|||||||
await expect(tx).to.revertWith(options.revertError);
|
await expect(tx).to.revertWith(options.revertError);
|
||||||
} else {
|
} else {
|
||||||
const gasUsed = (await tx).gasUsed;
|
const gasUsed = (await tx).gasUsed;
|
||||||
const ordersInfoAfter = await Promise.all(
|
const orderStatusesAfter = await Promise.all(
|
||||||
orders.map(order => this._exchangeWrapper.getOrderInfoAsync(order)),
|
orders.map(async order => (await this._exchangeWrapper.getOrderInfoAsync(order)).orderStatus),
|
||||||
);
|
);
|
||||||
const orderStatusesAfter = ordersInfoAfter.map(orderInfo => orderInfo.orderStatus);
|
|
||||||
|
|
||||||
await this._checkResultsAsync(
|
await this._checkResultsAsync(
|
||||||
fractionalNumberOfOrdersToFill,
|
fractionalNumberOfOrdersToFill,
|
||||||
@ -303,6 +201,7 @@ export class ForwarderTestFactory {
|
|||||||
.minus(expectedResults.makerAssetFillAmount)
|
.minus(expectedResults.makerAssetFillAmount)
|
||||||
.minus(expectedResults.maxOverboughtMakerAsset),
|
.minus(expectedResults.maxOverboughtMakerAsset),
|
||||||
oldBalances[this._makerAddress][makerAssetAddress].minus(expectedResults.makerAssetFillAmount),
|
oldBalances[this._makerAddress][makerAssetAddress].minus(expectedResults.makerAssetFillAmount),
|
||||||
|
'Maker makerAsset balance',
|
||||||
);
|
);
|
||||||
expectBalanceWithin(
|
expectBalanceWithin(
|
||||||
newBalances[this._takerAddress][makerAssetAddress],
|
newBalances[this._takerAddress][makerAssetAddress],
|
||||||
@ -313,11 +212,18 @@ export class ForwarderTestFactory {
|
|||||||
.plus(expectedResults.makerAssetFillAmount)
|
.plus(expectedResults.makerAssetFillAmount)
|
||||||
.minus(expectedResults.percentageFees)
|
.minus(expectedResults.percentageFees)
|
||||||
.plus(expectedResults.maxOverboughtMakerAsset),
|
.plus(expectedResults.maxOverboughtMakerAsset),
|
||||||
|
'Taker makerAsset balance',
|
||||||
);
|
);
|
||||||
expect(newBalances[this._orderFeeRecipientAddress][makerAssetAddress]).to.be.bignumber.equal(
|
expect(
|
||||||
|
newBalances[this._orderFeeRecipientAddress][makerAssetAddress],
|
||||||
|
'Order fee recipient makerAsset balance',
|
||||||
|
).to.be.bignumber.equal(
|
||||||
oldBalances[this._orderFeeRecipientAddress][makerAssetAddress].plus(expectedResults.percentageFees),
|
oldBalances[this._orderFeeRecipientAddress][makerAssetAddress].plus(expectedResults.percentageFees),
|
||||||
);
|
);
|
||||||
expect(newBalances[this._forwarderAddress][makerAssetAddress]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
expect(
|
||||||
|
newBalances[this._forwarderAddress][makerAssetAddress],
|
||||||
|
'Forwarder contract makerAsset balance',
|
||||||
|
).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _checkResultsAsync(
|
private async _checkResultsAsync(
|
||||||
@ -340,18 +246,17 @@ export class ForwarderTestFactory {
|
|||||||
if (fractionalNumberOfOrdersToFill >= i + 1 && orderStatusesBefore[i] === OrderStatus.Fillable) {
|
if (fractionalNumberOfOrdersToFill >= i + 1 && orderStatusesBefore[i] === OrderStatus.Fillable) {
|
||||||
expectedOrderStatus = OrderStatus.FullyFilled;
|
expectedOrderStatus = OrderStatus.FullyFilled;
|
||||||
}
|
}
|
||||||
|
expect(orderStatus, ` Order ${i} status`).to.equal(expectedOrderStatus);
|
||||||
expect(orderStatus).to.equal(expectedOrderStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wethSpent = expectedResults.takerAssetFillAmount
|
||||||
|
.plus(expectedResults.protocolFees)
|
||||||
|
.plus(expectedResults.wethFees);
|
||||||
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(
|
const ethSpentOnForwarderFee = ForwarderTestFactory.getPercentageOfValue(
|
||||||
expectedResults.takerAssetFillAmount,
|
wethSpent,
|
||||||
options.forwarderFeePercentage || constants.ZERO_AMOUNT,
|
options.forwarderFeePercentage || constants.ZERO_AMOUNT,
|
||||||
);
|
);
|
||||||
const totalEthSpent = expectedResults.takerAssetFillAmount
|
const totalEthSpent = wethSpent.plus(ethSpentOnForwarderFee).plus(this._gasPrice.times(gasUsed));
|
||||||
.plus(expectedResults.wethFees)
|
|
||||||
.plus(ethSpentOnForwarderFee)
|
|
||||||
.plus(this._gasPrice.times(gasUsed));
|
|
||||||
|
|
||||||
const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(this._takerAddress);
|
const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(this._takerAddress);
|
||||||
const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(this._forwarderAddress);
|
const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(this._forwarderAddress);
|
||||||
@ -361,12 +266,13 @@ export class ForwarderTestFactory {
|
|||||||
takerEthBalanceAfter,
|
takerEthBalanceAfter,
|
||||||
takerEthBalanceBefore.minus(totalEthSpent).minus(expectedResults.maxOversoldWeth),
|
takerEthBalanceBefore.minus(totalEthSpent).minus(expectedResults.maxOversoldWeth),
|
||||||
takerEthBalanceBefore.minus(totalEthSpent),
|
takerEthBalanceBefore.minus(totalEthSpent),
|
||||||
|
'Taker ETH balance',
|
||||||
);
|
);
|
||||||
if (options.forwarderFeeRecipientEthBalanceBefore !== undefined) {
|
if (options.forwarderFeeRecipientEthBalanceBefore !== undefined) {
|
||||||
const fowarderFeeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(
|
const fowarderFeeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(
|
||||||
this._forwarderFeeRecipientAddress,
|
this._forwarderFeeRecipientAddress,
|
||||||
);
|
);
|
||||||
expect(fowarderFeeRecipientEthBalanceAfter).to.be.bignumber.equal(
|
expect(fowarderFeeRecipientEthBalanceAfter, 'Forwarder fee recipient ETH balance').to.be.bignumber.equal(
|
||||||
options.forwarderFeeRecipientEthBalanceBefore.plus(ethSpentOnForwarderFee),
|
options.forwarderFeeRecipientEthBalanceBefore.plus(ethSpentOnForwarderFee),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -375,7 +281,7 @@ export class ForwarderTestFactory {
|
|||||||
this._checkErc20Balances(erc20Balances, newBalances, expectedResults, makerAssetContract);
|
this._checkErc20Balances(erc20Balances, newBalances, expectedResults, makerAssetContract);
|
||||||
} else if (options.makerAssetId !== undefined) {
|
} else if (options.makerAssetId !== undefined) {
|
||||||
const newOwner = await makerAssetContract.ownerOf.callAsync(options.makerAssetId);
|
const newOwner = await makerAssetContract.ownerOf.callAsync(options.makerAssetId);
|
||||||
expect(newOwner).to.be.bignumber.equal(this._takerAddress);
|
expect(newOwner, 'New ERC721 owner').to.be.bignumber.equal(this._takerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
expectBalanceWithin(
|
expectBalanceWithin(
|
||||||
@ -384,12 +290,97 @@ export class ForwarderTestFactory {
|
|||||||
erc20Balances[this._makerAddress][this._wethAddress]
|
erc20Balances[this._makerAddress][this._wethAddress]
|
||||||
.plus(expectedResults.takerAssetFillAmount)
|
.plus(expectedResults.takerAssetFillAmount)
|
||||||
.plus(expectedResults.maxOversoldWeth),
|
.plus(expectedResults.maxOversoldWeth),
|
||||||
|
'Maker WETH balance',
|
||||||
);
|
);
|
||||||
expect(newBalances[this._orderFeeRecipientAddress][this._wethAddress]).to.be.bignumber.equal(
|
expect(
|
||||||
|
newBalances[this._orderFeeRecipientAddress][this._wethAddress],
|
||||||
|
'Order fee recipient WETH balance',
|
||||||
|
).to.be.bignumber.equal(
|
||||||
erc20Balances[this._orderFeeRecipientAddress][this._wethAddress].plus(expectedResults.wethFees),
|
erc20Balances[this._orderFeeRecipientAddress][this._wethAddress].plus(expectedResults.wethFees),
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
expect(newBalances[this._forwarderAddress][this._wethAddress]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
newBalances[this._forwarderAddress][this._wethAddress],
|
||||||
|
'Forwarder contract WETH balance',
|
||||||
|
).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simulates filling some orders via the Forwarder contract. For example, if
|
||||||
|
// orders = [A, B, C, D] and fractionalNumberOfOrdersToFill = 2.3, then
|
||||||
|
// we simulate A and B being completely filled, and 0.3 * C being filled.
|
||||||
|
private _computeExpectedResults(
|
||||||
|
orders: SignedOrder[],
|
||||||
|
ordersInfoBefore: OrderInfo[],
|
||||||
|
fractionalNumberOfOrdersToFill: number,
|
||||||
|
): ForwarderFillState {
|
||||||
|
const currentState = {
|
||||||
|
takerAssetFillAmount: constants.ZERO_AMOUNT,
|
||||||
|
makerAssetFillAmount: constants.ZERO_AMOUNT,
|
||||||
|
protocolFees: constants.ZERO_AMOUNT,
|
||||||
|
wethFees: constants.ZERO_AMOUNT,
|
||||||
|
percentageFees: constants.ZERO_AMOUNT,
|
||||||
|
maxOversoldWeth: constants.ZERO_AMOUNT,
|
||||||
|
maxOverboughtMakerAsset: constants.ZERO_AMOUNT,
|
||||||
|
};
|
||||||
|
let remainingOrdersToFill = fractionalNumberOfOrdersToFill;
|
||||||
|
|
||||||
|
for (const [i, order] of orders.entries()) {
|
||||||
|
if (remainingOrdersToFill === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ordersInfoBefore[i].orderStatus !== OrderStatus.Fillable) {
|
||||||
|
// If the order is not fillable, skip over it but still count it towards fractionalNumberOfOrdersToFill
|
||||||
|
remainingOrdersToFill = Math.max(remainingOrdersToFill - 1, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let makerAssetAmount;
|
||||||
|
let takerAssetAmount;
|
||||||
|
let takerFee;
|
||||||
|
if (remainingOrdersToFill < 1) {
|
||||||
|
makerAssetAmount = order.makerAssetAmount.times(remainingOrdersToFill).integerValue();
|
||||||
|
takerAssetAmount = order.takerAssetAmount.times(remainingOrdersToFill).integerValue();
|
||||||
|
takerFee = order.takerFee.times(remainingOrdersToFill).integerValue();
|
||||||
|
|
||||||
|
// Up to 1 wei worth of WETH will be oversold on the last order due to rounding
|
||||||
|
currentState.maxOversoldWeth = new BigNumber(1);
|
||||||
|
// Equivalently, up to 1 wei worth of maker asset will be overbought
|
||||||
|
currentState.maxOverboughtMakerAsset = currentState.maxOversoldWeth
|
||||||
|
.times(order.makerAssetAmount)
|
||||||
|
.dividedToIntegerBy(order.takerAssetAmount);
|
||||||
|
} else {
|
||||||
|
makerAssetAmount = order.makerAssetAmount;
|
||||||
|
takerAssetAmount = order.takerAssetAmount;
|
||||||
|
takerFee = order.takerFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accounting for partially filled orders
|
||||||
|
// As with unfillable orders, these still count as 1 towards fractionalNumberOfOrdersToFill
|
||||||
|
const takerAssetFilled = ordersInfoBefore[i].orderTakerAssetFilledAmount;
|
||||||
|
const makerAssetFilled = takerAssetFilled
|
||||||
|
.times(order.makerAssetAmount)
|
||||||
|
.dividedToIntegerBy(order.takerAssetAmount);
|
||||||
|
takerAssetAmount = BigNumber.max(takerAssetAmount.minus(takerAssetFilled), constants.ZERO_AMOUNT);
|
||||||
|
makerAssetAmount = BigNumber.max(makerAssetAmount.minus(makerAssetFilled), constants.ZERO_AMOUNT);
|
||||||
|
|
||||||
|
currentState.takerAssetFillAmount = currentState.takerAssetFillAmount.plus(takerAssetAmount);
|
||||||
|
currentState.makerAssetFillAmount = currentState.makerAssetFillAmount.plus(makerAssetAmount);
|
||||||
|
|
||||||
|
if (this._protocolFeeCollectorAddress !== constants.NULL_ADDRESS) {
|
||||||
|
currentState.protocolFees = currentState.protocolFees.plus(
|
||||||
|
this._gasPrice.times(this._protocolFeeMultiplier),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (order.takerFeeAssetData === order.makerAssetData) {
|
||||||
|
currentState.percentageFees = currentState.percentageFees.plus(takerFee);
|
||||||
|
} else if (order.takerFeeAssetData === order.takerAssetData) {
|
||||||
|
currentState.wethFees = currentState.wethFees.plus(takerFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingOrdersToFill = Math.max(remainingOrdersToFill - 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
"generated-artifacts/MixinAssets.json",
|
"generated-artifacts/MixinAssets.json",
|
||||||
"generated-artifacts/MixinExchangeWrapper.json",
|
"generated-artifacts/MixinExchangeWrapper.json",
|
||||||
"generated-artifacts/MixinForwarderCore.json",
|
"generated-artifacts/MixinForwarderCore.json",
|
||||||
"generated-artifacts/MixinWeth.json"
|
"generated-artifacts/MixinWeth.json",
|
||||||
|
"generated-artifacts/TestProtocolFeeCollector.json"
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ blockchainTests.resets('Exchange core', () => {
|
|||||||
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address, { from: owner });
|
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address, { from: owner });
|
||||||
|
|
||||||
// Configure Exchange
|
// Configure Exchange
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
exchangeWrapper = new ExchangeWrapper(exchange);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
|
||||||
|
@ -135,7 +135,7 @@ describe('matchOrders', () => {
|
|||||||
{},
|
{},
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
exchangeWrapper = new ExchangeWrapper(exchange);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
|
||||||
|
@ -96,7 +96,7 @@ blockchainTests.resets('Exchange transactions', env => {
|
|||||||
{},
|
{},
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
exchangeWrapper = new ExchangeWrapper(exchangeInstance, env.provider);
|
exchangeWrapper = new ExchangeWrapper(exchangeInstance);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
|
|
||||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeInstance.address, { from: owner });
|
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeInstance.address, { from: owner });
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { BatchMatchOrder, orderUtils, Web3ProviderEngine } from '@0x/contracts-test-utils';
|
import { BatchMatchOrder, orderUtils } from '@0x/contracts-test-utils';
|
||||||
import {
|
import {
|
||||||
BatchMatchedFillResults,
|
BatchMatchedFillResults,
|
||||||
FillResults,
|
FillResults,
|
||||||
@ -8,7 +8,7 @@ import {
|
|||||||
SignedZeroExTransaction,
|
SignedZeroExTransaction,
|
||||||
} from '@0x/types';
|
} from '@0x/types';
|
||||||
import { AbiEncoder, BigNumber } from '@0x/utils';
|
import { AbiEncoder, BigNumber } from '@0x/utils';
|
||||||
import { MethodAbi, TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types';
|
import { MethodAbi, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ExchangeContract } from '../../src';
|
import { ExchangeContract } from '../../src';
|
||||||
@ -16,18 +16,15 @@ import { ExchangeContract } from '../../src';
|
|||||||
import { AbiDecodedFillOrderData } from './types';
|
import { AbiDecodedFillOrderData } from './types';
|
||||||
|
|
||||||
export class ExchangeWrapper {
|
export class ExchangeWrapper {
|
||||||
private readonly _exchange: ExchangeContract;
|
constructor(public readonly exchangeContract: ExchangeContract) {}
|
||||||
// tslint:disable no-unused-variable
|
|
||||||
constructor(exchangeContract: ExchangeContract, provider: Web3ProviderEngine | ZeroExProvider) {
|
|
||||||
this._exchange = exchangeContract;
|
|
||||||
}
|
|
||||||
public async fillOrderAsync(
|
public async fillOrderAsync(
|
||||||
signedOrder: SignedOrder,
|
signedOrder: SignedOrder,
|
||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmount?: BigNumber } = {},
|
opts: { takerAssetFillAmount?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||||
const txReceipt = await this._exchange.fillOrder.awaitTransactionSuccessAsync(
|
const txReceipt = await this.exchangeContract.fillOrder.awaitTransactionSuccessAsync(
|
||||||
params.order,
|
params.order,
|
||||||
params.takerAssetFillAmount,
|
params.takerAssetFillAmount,
|
||||||
params.signature,
|
params.signature,
|
||||||
@ -37,7 +34,7 @@ export class ExchangeWrapper {
|
|||||||
}
|
}
|
||||||
public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createCancel(signedOrder);
|
const params = orderUtils.createCancel(signedOrder);
|
||||||
const txReceipt = await this._exchange.cancelOrder.awaitTransactionSuccessAsync(params.order, { from });
|
const txReceipt = await this.exchangeContract.cancelOrder.awaitTransactionSuccessAsync(params.order, { from });
|
||||||
return txReceipt;
|
return txReceipt;
|
||||||
}
|
}
|
||||||
public async fillOrKillOrderAsync(
|
public async fillOrKillOrderAsync(
|
||||||
@ -46,7 +43,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
|
opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||||
const txReceipt = await this._exchange.fillOrKillOrder.awaitTransactionSuccessAsync(
|
const txReceipt = await this.exchangeContract.fillOrKillOrder.awaitTransactionSuccessAsync(
|
||||||
params.order,
|
params.order,
|
||||||
params.takerAssetFillAmount,
|
params.takerAssetFillAmount,
|
||||||
params.signature,
|
params.signature,
|
||||||
@ -59,7 +56,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
|
opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchFillOrders.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchFillOrders.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.takerAssetFillAmounts === undefined
|
opts.takerAssetFillAmounts === undefined
|
||||||
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
||||||
@ -73,7 +70,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
|
opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchFillOrKillOrders.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchFillOrKillOrders.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.takerAssetFillAmounts === undefined
|
opts.takerAssetFillAmounts === undefined
|
||||||
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
||||||
@ -87,7 +84,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number; gasPrice?: BigNumber } = {},
|
opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number; gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchFillOrdersNoThrow.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchFillOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.takerAssetFillAmounts === undefined
|
opts.takerAssetFillAmounts === undefined
|
||||||
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
? orders.map(signedOrder => signedOrder.takerAssetAmount)
|
||||||
@ -101,7 +98,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
|
opts: { takerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.marketSellOrdersNoThrow.awaitTransactionSuccessAsync(
|
return this.exchangeContract.marketSellOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.takerAssetFillAmount,
|
opts.takerAssetFillAmount,
|
||||||
orders.map(signedOrder => signedOrder.signature),
|
orders.map(signedOrder => signedOrder.signature),
|
||||||
@ -113,7 +110,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { makerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
|
opts: { makerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.marketBuyOrdersNoThrow.awaitTransactionSuccessAsync(
|
return this.exchangeContract.marketBuyOrdersNoThrow.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.makerAssetFillAmount,
|
opts.makerAssetFillAmount,
|
||||||
orders.map(signedOrder => signedOrder.signature),
|
orders.map(signedOrder => signedOrder.signature),
|
||||||
@ -125,7 +122,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { takerAssetFillAmount: BigNumber; gas?: number },
|
opts: { takerAssetFillAmount: BigNumber; gas?: number },
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.marketSellOrdersFillOrKill.awaitTransactionSuccessAsync(
|
return this.exchangeContract.marketSellOrdersFillOrKill.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.takerAssetFillAmount,
|
opts.takerAssetFillAmount,
|
||||||
orders.map(signedOrder => signedOrder.signature),
|
orders.map(signedOrder => signedOrder.signature),
|
||||||
@ -137,7 +134,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { makerAssetFillAmount: BigNumber; gas?: number },
|
opts: { makerAssetFillAmount: BigNumber; gas?: number },
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.marketBuyOrdersFillOrKill.awaitTransactionSuccessAsync(
|
return this.exchangeContract.marketBuyOrdersFillOrKill.awaitTransactionSuccessAsync(
|
||||||
orders,
|
orders,
|
||||||
opts.makerAssetFillAmount,
|
opts.makerAssetFillAmount,
|
||||||
orders.map(signedOrder => signedOrder.signature),
|
orders.map(signedOrder => signedOrder.signature),
|
||||||
@ -148,19 +145,22 @@ export class ExchangeWrapper {
|
|||||||
orders: SignedOrder[],
|
orders: SignedOrder[],
|
||||||
from: string,
|
from: string,
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchCancelOrders.awaitTransactionSuccessAsync(orders, { from });
|
return this.exchangeContract.batchCancelOrders.awaitTransactionSuccessAsync(orders, { from });
|
||||||
}
|
}
|
||||||
public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const txReceipt = await this._exchange.cancelOrdersUpTo.awaitTransactionSuccessAsync(salt, { from });
|
const txReceipt = await this.exchangeContract.cancelOrdersUpTo.awaitTransactionSuccessAsync(salt, { from });
|
||||||
return txReceipt;
|
return txReceipt;
|
||||||
}
|
}
|
||||||
public async registerAssetProxyAsync(
|
public async registerAssetProxyAsync(
|
||||||
assetProxyAddress: string,
|
assetProxyAddress: string,
|
||||||
from: string,
|
from: string,
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const txReceipt = await this._exchange.registerAssetProxy.awaitTransactionSuccessAsync(assetProxyAddress, {
|
const txReceipt = await this.exchangeContract.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||||
|
assetProxyAddress,
|
||||||
|
{
|
||||||
from,
|
from,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
return txReceipt;
|
return txReceipt;
|
||||||
}
|
}
|
||||||
public async executeTransactionAsync(
|
public async executeTransactionAsync(
|
||||||
@ -168,7 +168,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.executeTransaction.awaitTransactionSuccessAsync(
|
return this.exchangeContract.executeTransaction.awaitTransactionSuccessAsync(
|
||||||
signedTransaction,
|
signedTransaction,
|
||||||
signedTransaction.signature,
|
signedTransaction.signature,
|
||||||
{ from, gasPrice: opts.gasPrice },
|
{ from, gasPrice: opts.gasPrice },
|
||||||
@ -180,25 +180,29 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const signatures = signedTransactions.map(signedTransaction => signedTransaction.signature);
|
const signatures = signedTransactions.map(signedTransaction => signedTransaction.signature);
|
||||||
return this._exchange.batchExecuteTransactions.awaitTransactionSuccessAsync(signedTransactions, signatures, {
|
return this.exchangeContract.batchExecuteTransactions.awaitTransactionSuccessAsync(
|
||||||
|
signedTransactions,
|
||||||
|
signatures,
|
||||||
|
{
|
||||||
from,
|
from,
|
||||||
gasPrice: opts.gasPrice,
|
gasPrice: opts.gasPrice,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
|
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
|
||||||
const filledAmount = await this._exchange.filled.callAsync(orderHashHex);
|
const filledAmount = await this.exchangeContract.filled.callAsync(orderHashHex);
|
||||||
return filledAmount;
|
return filledAmount;
|
||||||
}
|
}
|
||||||
public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
|
public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
|
||||||
const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex);
|
const isCancelled = await this.exchangeContract.cancelled.callAsync(orderHashHex);
|
||||||
return isCancelled;
|
return isCancelled;
|
||||||
}
|
}
|
||||||
public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
|
public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
|
||||||
const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress);
|
const orderEpoch = await this.exchangeContract.orderEpoch.callAsync(makerAddress, senderAddress);
|
||||||
return orderEpoch;
|
return orderEpoch;
|
||||||
}
|
}
|
||||||
public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
|
public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
|
||||||
const orderInfo = await this._exchange.getOrderInfo.callAsync(signedOrder);
|
const orderInfo = await this.exchangeContract.getOrderInfo.callAsync(signedOrder);
|
||||||
return orderInfo;
|
return orderInfo;
|
||||||
}
|
}
|
||||||
public async batchMatchOrdersAsync(
|
public async batchMatchOrdersAsync(
|
||||||
@ -208,7 +212,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
||||||
return this._exchange.batchMatchOrders.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchMatchOrders.awaitTransactionSuccessAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -221,7 +225,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchMatchOrders.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchMatchOrders.awaitTransactionSuccessAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -236,7 +240,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<BatchMatchedFillResults> {
|
): Promise<BatchMatchedFillResults> {
|
||||||
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
||||||
const batchMatchedFillResults = await this._exchange.batchMatchOrders.callAsync(
|
const batchMatchedFillResults = await this.exchangeContract.batchMatchOrders.callAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -252,7 +256,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
||||||
return this._exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -265,7 +269,7 @@ export class ExchangeWrapper {
|
|||||||
from: string,
|
from: string,
|
||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
return this._exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
return this.exchangeContract.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -280,7 +284,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<BatchMatchedFillResults> {
|
): Promise<BatchMatchedFillResults> {
|
||||||
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
|
||||||
const batchMatchedFillResults = await this._exchange.batchMatchOrdersWithMaximalFill.callAsync(
|
const batchMatchedFillResults = await this.exchangeContract.batchMatchOrdersWithMaximalFill.callAsync(
|
||||||
params.leftOrders,
|
params.leftOrders,
|
||||||
params.rightOrders,
|
params.rightOrders,
|
||||||
params.leftSignatures,
|
params.leftSignatures,
|
||||||
@ -296,7 +300,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
||||||
const txReceipt = await this._exchange.matchOrders.awaitTransactionSuccessAsync(
|
const txReceipt = await this.exchangeContract.matchOrders.awaitTransactionSuccessAsync(
|
||||||
params.left,
|
params.left,
|
||||||
params.right,
|
params.right,
|
||||||
params.leftSignature,
|
params.leftSignature,
|
||||||
@ -312,7 +316,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<MatchedFillResults> {
|
): Promise<MatchedFillResults> {
|
||||||
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
||||||
const matchedFillResults = await this._exchange.matchOrders.callAsync(
|
const matchedFillResults = await this.exchangeContract.matchOrders.callAsync(
|
||||||
params.left,
|
params.left,
|
||||||
params.right,
|
params.right,
|
||||||
params.leftSignature,
|
params.leftSignature,
|
||||||
@ -328,7 +332,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber } = {},
|
opts: { gasPrice?: BigNumber } = {},
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
||||||
return this._exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
return this.exchangeContract.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
|
||||||
params.left,
|
params.left,
|
||||||
params.right,
|
params.right,
|
||||||
params.leftSignature,
|
params.leftSignature,
|
||||||
@ -343,7 +347,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { gasPrice?: BigNumber },
|
opts: { gasPrice?: BigNumber },
|
||||||
): Promise<MatchedFillResults> {
|
): Promise<MatchedFillResults> {
|
||||||
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
|
||||||
const matchedFillResults = await this._exchange.matchOrdersWithMaximalFill.callAsync(
|
const matchedFillResults = await this.exchangeContract.matchOrdersWithMaximalFill.callAsync(
|
||||||
params.left,
|
params.left,
|
||||||
params.right,
|
params.right,
|
||||||
params.leftSignature,
|
params.leftSignature,
|
||||||
@ -358,7 +362,7 @@ export class ExchangeWrapper {
|
|||||||
opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
|
opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
|
||||||
): Promise<FillResults> {
|
): Promise<FillResults> {
|
||||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||||
const fillResults = await this._exchange.fillOrder.callAsync(
|
const fillResults = await this.exchangeContract.fillOrder.callAsync(
|
||||||
params.order,
|
params.order,
|
||||||
params.takerAssetFillAmount,
|
params.takerAssetFillAmount,
|
||||||
params.signature,
|
params.signature,
|
||||||
@ -368,7 +372,7 @@ export class ExchangeWrapper {
|
|||||||
}
|
}
|
||||||
public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string {
|
public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string {
|
||||||
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
|
||||||
const data = this._exchange.fillOrder.getABIEncodedTransactionData(
|
const data = this.exchangeContract.fillOrder.getABIEncodedTransactionData(
|
||||||
params.order,
|
params.order,
|
||||||
params.takerAssetFillAmount,
|
params.takerAssetFillAmount,
|
||||||
params.signature,
|
params.signature,
|
||||||
@ -377,13 +381,10 @@ export class ExchangeWrapper {
|
|||||||
}
|
}
|
||||||
public abiDecodeFillOrder(data: string): AbiDecodedFillOrderData {
|
public abiDecodeFillOrder(data: string): AbiDecodedFillOrderData {
|
||||||
// Lookup fillOrder ABI in exchange abi
|
// Lookup fillOrder ABI in exchange abi
|
||||||
const fillOrderAbi = _.find(this._exchange.abi, { name: 'fillOrder' }) as MethodAbi;
|
const fillOrderAbi = _.find(this.exchangeContract.abi, { name: 'fillOrder' }) as MethodAbi;
|
||||||
// Decode input data
|
// Decode input data
|
||||||
const abiEncoder = new AbiEncoder.Method(fillOrderAbi);
|
const abiEncoder = new AbiEncoder.Method(fillOrderAbi);
|
||||||
const decodedData = abiEncoder.decode(data) as AbiDecodedFillOrderData;
|
const decodedData = abiEncoder.decode(data) as AbiDecodedFillOrderData;
|
||||||
return decodedData;
|
return decodedData;
|
||||||
}
|
}
|
||||||
public getExchangeAddress(): string {
|
|
||||||
return this._exchange.address;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const logDecoder = new LogDecoder(web3Wrapper, artifacts);
|
const logDecoder = new LogDecoder(web3Wrapper, artifacts);
|
||||||
const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider);
|
const exchangeWrapper = new ExchangeWrapper(exchangeContract);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, ownerAddress);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, ownerAddress);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, ownerAddress);
|
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, ownerAddress);
|
||||||
@ -646,7 +646,7 @@ export class FillOrderCombinatorialUtils {
|
|||||||
|
|
||||||
const exchangeLogs = _.filter(
|
const exchangeLogs = _.filter(
|
||||||
txReceipt.logs,
|
txReceipt.logs,
|
||||||
txLog => txLog.address === this.exchangeWrapper.getExchangeAddress(),
|
txLog => txLog.address === this.exchangeWrapper.exchangeContract.address,
|
||||||
);
|
);
|
||||||
expect(exchangeLogs.length).to.be.equal(1, 'logs length');
|
expect(exchangeLogs.length).to.be.equal(1, 'logs length');
|
||||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||||
|
@ -78,7 +78,7 @@ blockchainTests.resets('Exchange wrappers', env => {
|
|||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
|
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, env.provider);
|
exchangeWrapper = new ExchangeWrapper(exchange);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
|
|
||||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, {
|
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, {
|
||||||
|
@ -136,7 +136,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
|
|||||||
zrxAssetData,
|
zrxAssetData,
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
|
exchangeWrapper = new ExchangeWrapper(exchangeInstance);
|
||||||
// Register proxies
|
// Register proxies
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
|
||||||
|
@ -95,7 +95,7 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
zrxAssetData,
|
zrxAssetData,
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
|
const exchangeWrapper = new ExchangeWrapper(exchangeInstance);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ describe('OrderMatcher', () => {
|
|||||||
assetDataUtils.encodeERC20AssetData(zrxToken.address),
|
assetDataUtils.encodeERC20AssetData(zrxToken.address),
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
exchangeWrapper = new ExchangeWrapper(exchange);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||||
// Authorize ERC20 trades by exchange
|
// Authorize ERC20 trades by exchange
|
||||||
|
@ -20,10 +20,10 @@ export class OrderFactory {
|
|||||||
const tenMinutesInSeconds = 10 * 60;
|
const tenMinutesInSeconds = 10 * 60;
|
||||||
const currentBlockTimestamp = await getLatestBlockTimestampAsync();
|
const currentBlockTimestamp = await getLatestBlockTimestampAsync();
|
||||||
const order = ({
|
const order = ({
|
||||||
|
takerAddress: constants.NULL_ADDRESS,
|
||||||
senderAddress: constants.NULL_ADDRESS,
|
senderAddress: constants.NULL_ADDRESS,
|
||||||
expirationTimeSeconds: new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds),
|
expirationTimeSeconds: new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds),
|
||||||
salt: generatePseudoRandomSalt(),
|
salt: generatePseudoRandomSalt(),
|
||||||
takerAddress: constants.NULL_ADDRESS,
|
|
||||||
...this._defaultOrderParams,
|
...this._defaultOrderParams,
|
||||||
...customOrderParams,
|
...customOrderParams,
|
||||||
} as any) as Order;
|
} as any) as Order;
|
||||||
|
@ -64,10 +64,10 @@ export class InsufficientEthForFeeError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OversoldWethError extends RevertError {
|
export class OverspentWethError extends RevertError {
|
||||||
constructor(wethSold?: BigNumber | number | string, msgValue?: BigNumber | number | string) {
|
constructor(wethSpent?: BigNumber | number | string, msgValue?: BigNumber | number | string) {
|
||||||
super('OversoldWethError', 'OversoldWethError(uint256 wethSold, uint256 msgValue)', {
|
super('OverspentWethError', 'OverspentWethError(uint256 wethSpent, uint256 msgValue)', {
|
||||||
wethSold,
|
wethSpent,
|
||||||
msgValue,
|
msgValue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -87,9 +87,9 @@ export class DefaultFunctionWethContractOnlyError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MsgValueCantEqualZeroError extends RevertError {
|
export class MsgValueCannotEqualZeroError extends RevertError {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('MsgValueCantEqualZeroError', 'MsgValueCantEqualZeroError()', {});
|
super('MsgValueCannotEqualZeroError', 'MsgValueCannotEqualZeroError()', {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +109,10 @@ const types = [
|
|||||||
UnsupportedFeeError,
|
UnsupportedFeeError,
|
||||||
FeePercentageTooLargeError,
|
FeePercentageTooLargeError,
|
||||||
InsufficientEthForFeeError,
|
InsufficientEthForFeeError,
|
||||||
OversoldWethError,
|
OverspentWethError,
|
||||||
TransferFailedError,
|
TransferFailedError,
|
||||||
DefaultFunctionWethContractOnlyError,
|
DefaultFunctionWethContractOnlyError,
|
||||||
MsgValueCantEqualZeroError,
|
MsgValueCannotEqualZeroError,
|
||||||
Erc721AmountMustEqualOneError,
|
Erc721AmountMustEqualOneError,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ export function getThrownErrorRevertErrorBytes(error: Error | GanacheTransaction
|
|||||||
// so we do nothing.
|
// so we do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error(`Cannot decode thrown Errror "${error.message}" as a RevertError`);
|
throw new Error(`Cannot decode thrown Error "${error.message}" as a RevertError`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isGanacheTransactionRevertError(
|
function isGanacheTransactionRevertError(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user