Add marketBuyOrders, rename variables, and fx old tests

This commit is contained in:
Amir Bandeali
2018-03-29 11:08:52 -07:00
parent 7a66da5a51
commit 75f77f3e86
11 changed files with 681 additions and 645 deletions

View File

@@ -28,10 +28,10 @@ contract LibOrder {
"address makerTokenAddress",
"address takerTokenAddress",
"address feeRecipientAddress",
"uint256 makerTokenAmount",
"uint256 takerTokenAmount",
"uint256 makerFeeAmount",
"uint256 takerFeeAmount",
"uint256 makerSellAmount",
"uint256 makerBuyAmount",
"uint256 makerFee",
"uint256 takerFee",
"uint256 expirationTimeSeconds",
"uint256 salt"
);
@@ -42,10 +42,10 @@ contract LibOrder {
address makerTokenAddress;
address takerTokenAddress;
address feeRecipientAddress;
uint256 makerTokenAmount;
uint256 takerTokenAmount;
uint256 makerFeeAmount;
uint256 takerFeeAmount;
uint256 makerSellAmount;
uint256 makerBuyAmount;
uint256 makerFee;
uint256 takerFee;
uint256 expirationTimeSeconds;
uint256 salt;
}
@@ -68,10 +68,10 @@ contract LibOrder {
order.makerTokenAddress,
order.takerTokenAddress,
order.feeRecipientAddress,
order.makerTokenAmount,
order.takerTokenAmount,
order.makerFeeAmount,
order.takerFeeAmount,
order.makerSellAmount,
order.makerBuyAmount,
order.makerFee,
order.takerFee,
order.expirationTimeSeconds,
order.salt
)

View File

@@ -39,8 +39,10 @@ contract MixinExchangeCore is
LibErrors,
LibPartialAmount
{
// Mappings of orderHash => amounts of takerTokenAmount filled or cancelled.
// Mapping of orderHash => amount of takerToken already bought by maker
mapping (bytes32 => uint256) public filled;
// Mapping of orderHash => cancelled
mapping (bytes32 => bool) public cancelled;
// Mapping of makerAddress => lowest salt an order can have in order to be fillable
@@ -53,10 +55,10 @@ contract MixinExchangeCore is
address indexed feeRecipientAddress,
address makerTokenAddress,
address takerTokenAddress,
uint256 makerTokenFilledAmount,
uint256 takerTokenFilledAmount,
uint256 makerFeeAmountPaid,
uint256 takerFeeAmountPaid,
uint256 makerAmountSold,
uint256 makerAmountBought,
uint256 makerFeePaid,
uint256 takerFeePaid,
bytes32 indexed orderHash
);
@@ -69,7 +71,7 @@ contract MixinExchangeCore is
);
event LogCancelUpTo(
address indexed maker,
address indexed makerAddress,
uint256 makerEpoch
);
@@ -79,15 +81,15 @@ contract MixinExchangeCore is
/// @dev Fills the input order.
/// @param order Order struct containing order specifications.
/// @param takerTokenFillAmount Desired amount of takerToken to fill.
/// @param takerSellAmount Desired amount of takerToken to sell.
/// @param signature Proof of signing order by maker.
/// @return Total amount of takerToken filled in trade.
function fillOrder(
Order order,
uint256 takerTokenFillAmount,
bytes signature)
Order memory order,
uint256 takerSellAmount,
bytes memory signature)
public
returns (uint256 takerTokenFilledAmount)
returns (uint256 takerAmountSold)
{
// Compute the order hash
bytes32 orderHash = getOrderHash(order);
@@ -101,8 +103,6 @@ contract MixinExchangeCore is
// Validate order and maker only if first time seen
// TODO: Read filled and cancelled only once
if (filled[orderHash] == 0) {
require(order.makerTokenAmount > 0);
require(order.takerTokenAmount > 0);
require(isValidSignature(orderHash, order.makerAddress, signature));
}
@@ -110,7 +110,6 @@ contract MixinExchangeCore is
if (order.takerAddress != address(0)) {
require(order.takerAddress == msg.sender);
}
require(takerTokenFillAmount > 0);
// Validate order expiration
if (block.timestamp >= order.expirationTimeSeconds) {
@@ -119,15 +118,15 @@ contract MixinExchangeCore is
}
// Validate order availability
uint256 remainingTakerTokenAmount = safeSub(order.takerTokenAmount, filled[orderHash]);
if (remainingTakerTokenAmount == 0) {
uint256 remainingMakerBuyAmount = safeSub(order.makerBuyAmount, filled[orderHash]);
if (remainingMakerBuyAmount == 0) {
LogError(uint8(Errors.ORDER_FULLY_FILLED), orderHash);
return 0;
}
// Validate fill order rounding
takerTokenFilledAmount = min256(takerTokenFillAmount, remainingTakerTokenAmount);
if (isRoundingError(takerTokenFilledAmount, order.takerTokenAmount, order.makerTokenAmount)) {
takerAmountSold = min256(takerSellAmount, remainingMakerBuyAmount);
if (isRoundingError(takerAmountSold, order.makerBuyAmount, order.makerSellAmount)) {
LogError(uint8(Errors.ROUNDING_ERROR_TOO_LARGE), orderHash);
return 0;
}
@@ -139,11 +138,11 @@ contract MixinExchangeCore is
}
// Update state
filled[orderHash] = safeAdd(filled[orderHash], takerTokenFilledAmount);
filled[orderHash] = safeAdd(filled[orderHash], takerAmountSold);
// Settle order
var (makerTokenFilledAmount, makerFeeAmountPaid, takerFeeAmountPaid) =
settleOrder(order, msg.sender, takerTokenFilledAmount);
var (makerAmountSold, makerFeePaid, takerFeePaid) =
settleOrder(order, msg.sender, takerAmountSold);
// Log order
LogFill(
@@ -152,19 +151,19 @@ contract MixinExchangeCore is
order.feeRecipientAddress,
order.makerTokenAddress,
order.takerTokenAddress,
makerTokenFilledAmount,
takerTokenFilledAmount,
makerFeeAmountPaid,
takerFeeAmountPaid,
makerAmountSold,
takerAmountSold,
makerFeePaid,
takerFeePaid,
orderHash
);
return takerTokenFilledAmount;
return takerAmountSold;
}
/// @dev After calling, the order can not be filled anymore.
/// @param order Order struct containing order specifications.
/// @return True if the order state changed to cancelled. False if the transaction was already cancelled or expired.
function cancelOrder(Order order)
function cancelOrder(Order memory order)
public
returns (bool)
{
@@ -172,8 +171,6 @@ contract MixinExchangeCore is
bytes32 orderHash = getOrderHash(order);
// Validate the order
require(order.makerTokenAmount > 0);
require(order.takerTokenAmount > 0);
require(order.makerAddress == msg.sender);
if (block.timestamp >= order.expirationTimeSeconds) {

View File

@@ -48,32 +48,32 @@ contract MixinSettlementProxy is
}
function MixinSettlementProxy(
ITokenTransferProxy proxyContract,
IToken zrxToken)
ITokenTransferProxy _proxyContract,
IToken _zrxToken)
public
{
ZRX_TOKEN = zrxToken;
TRANSFER_PROXY = proxyContract;
ZRX_TOKEN = _zrxToken;
TRANSFER_PROXY = _proxyContract;
}
function settleOrder(
Order order,
Order memory order,
address takerAddress,
uint256 takerTokenFilledAmount)
uint256 takerAmountSold)
internal
returns (
uint256 makerTokenFilledAmount,
uint256 makerFeeAmountPaid,
uint256 takerFeeAmountPaid
uint256 makerAmountSold,
uint256 makerFeePaid,
uint256 takerFeePaid
)
{
makerTokenFilledAmount = getPartialAmount(takerTokenFilledAmount, order.takerTokenAmount, order.makerTokenAmount);
makerAmountSold = getPartialAmount(takerAmountSold, order.makerBuyAmount, order.makerSellAmount);
require(
TRANSFER_PROXY.transferFrom(
order.makerTokenAddress,
order.makerAddress,
takerAddress,
makerTokenFilledAmount
makerAmountSold
)
);
require(
@@ -81,33 +81,33 @@ contract MixinSettlementProxy is
order.takerTokenAddress,
takerAddress,
order.makerAddress,
takerTokenFilledAmount
takerAmountSold
)
);
if (order.feeRecipientAddress != address(0)) {
if (order.makerFeeAmount > 0) {
makerFeeAmountPaid = getPartialAmount(takerTokenFilledAmount, order.takerTokenAmount, order.makerFeeAmount);
if (order.makerFee > 0) {
makerFeePaid = getPartialAmount(takerAmountSold, order.makerBuyAmount, order.makerFee);
require(
TRANSFER_PROXY.transferFrom(
ZRX_TOKEN,
order.makerAddress,
order.feeRecipientAddress,
makerFeeAmountPaid
makerFeePaid
)
);
}
if (order.takerFeeAmount > 0) {
takerFeeAmountPaid = getPartialAmount(takerTokenFilledAmount, order.takerTokenAmount, order.takerFeeAmount);
if (order.takerFee > 0) {
takerFeePaid = getPartialAmount(takerAmountSold, order.makerBuyAmount, order.takerFee);
require(
TRANSFER_PROXY.transferFrom(
ZRX_TOKEN,
takerAddress,
order.feeRecipientAddress,
takerFeeAmountPaid
takerFeePaid
)
);
}
}
return (makerTokenFilledAmount, makerFeeAmountPaid, takerFeeAmountPaid);
return (makerAmountSold, makerFeePaid, takerFeePaid);
}
}

View File

@@ -20,42 +20,46 @@ pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
import "./mixins/MExchangeCore.sol";
import "./LibPartialAmount.sol";
import "../../utils/SafeMath/SafeMath.sol";
/// @dev Consumes MExchangeCore
contract MixinWrapperFunctions is
MExchangeCore,
SafeMath
SafeMath,
LibPartialAmount
{
/// @dev Fills the input order. Reverts if exact takerSellAmount not filled.
/// @param order Order struct containing order specifications.
/// @param takerTokenFillAmount Desired amount of takerToken to fill.
/// @param takerSellAmount Desired amount of takerToken to fill.
/// @param signature Maker's signature of the order.
function fillOrKillOrder(
Order order,
uint256 takerTokenFillAmount,
bytes signature)
Order memory order,
uint256 takerSellAmount,
bytes memory signature)
public
{
require(
fillOrder(
order,
takerTokenFillAmount,
takerSellAmount,
signature
) == takerTokenFillAmount
) == takerSellAmount
);
}
/// @dev Fills an order with specified parameters and ECDSA signature. Returns false if the transaction would otherwise revert.
/// @dev Fills an order with specified parameters and ECDSA signature.
/// Returns false if the transaction would otherwise revert.
/// @param order Order struct containing order specifications.
/// @param takerTokenFillAmount Desired amount of takerToken to fill.
/// @param takerSellAmount Desired amount of takerToken to fill.
/// @param signature Maker's signature of the order.
/// @return Total amount of takerToken filled in trade.
function fillOrderNoThrow(
Order order,
uint256 takerTokenFillAmount,
bytes signature)
Order memory order,
uint256 takerSellAmount,
bytes memory signature)
public
returns (uint256 takerTokenFilledAmount)
returns (uint256 takerAmountSold)
{
// We need to call MExchangeCore.fillOrder using a delegatecall in
// assembly so that we can intercept a call that throws. For this, we
@@ -101,8 +105,8 @@ contract MixinWrapperFunctions is
mstore(add(start, 292), mload(add(order, 288))) // expirationTimeSeconds
mstore(add(start, 324), mload(add(order, 320))) // salt
// Write takerTokenFillAmount
mstore(add(start, 356), takerTokenFillAmount)
// Write takerSellAmount
mstore(add(start, 356), takerSellAmount)
// Write signature offset
mstore(add(start, 388), 416)
@@ -133,30 +137,30 @@ contract MixinWrapperFunctions is
)
switch success
case 0 {
takerTokenFilledAmount := 0
takerAmountSold := 0
}
case 1 {
takerTokenFilledAmount := mload(start)
takerAmountSold := mload(start)
}
}
return takerTokenFilledAmount;
return takerAmountSold;
}
/// @dev Synchronously executes multiple calls of fillOrder in a single transaction.
/// @param orders Array of orders.
/// @param takerTokenFillAmounts Array of desired amounts of takerToken to fill in orders.
/// @param takerSellAmounts Array of desired amounts of takerToken to fill in orders.
/// @param signatures Maker's signatures of the orders.
function batchFillOrders(
Order[] orders,
uint256[] takerTokenFillAmounts,
bytes[] signatures)
Order[] memory orders,
uint256[] memory takerSellAmounts,
bytes[] memory signatures)
public
{
for (uint256 i = 0; i < orders.length; i++) {
fillOrder(
orders[i],
takerTokenFillAmounts[i],
takerSellAmounts[i],
signatures[i]
);
}
@@ -164,18 +168,18 @@ contract MixinWrapperFunctions is
/// @dev Synchronously executes multiple calls of fillOrKill in a single transaction.
/// @param orders Array of orders.
/// @param takerTokenFillAmounts Array of desired amounts of takerToken to fill in orders.
/// @param takerSellAmounts Array of desired amounts of takerToken to fill in orders.
/// @param signatures Maker's signatures of the orders.
function batchFillOrKillOrders(
Order[] orders,
uint256[] takerTokenFillAmounts,
bytes[] signatures)
Order[] memory orders,
uint256[] memory takerSellAmounts,
bytes[] memory signatures)
public
{
for (uint256 i = 0; i < orders.length; i++) {
fillOrKillOrder(
orders[i],
takerTokenFillAmounts[i],
takerSellAmounts[i],
signatures[i]
);
}
@@ -183,86 +187,168 @@ contract MixinWrapperFunctions is
/// @dev Fills an order with specified parameters and ECDSA signature. Returns false if the transaction would otherwise revert.
/// @param orders Array of orders.
/// @param takerTokenFillAmounts Array of desired amounts of takerToken to fill in orders.
/// @param takerSellAmounts Array of desired amounts of takerToken to fill in orders.
/// @param signatures Maker's signatures of the orders.
function batchFillOrdersNoThrow(
Order[] orders,
uint256[] takerTokenFillAmounts,
bytes[] signatures)
Order[] memory orders,
uint256[] memory takerSellAmounts,
bytes[] memory signatures)
public
{
for (uint256 i = 0; i < orders.length; i++) {
fillOrderNoThrow(
orders[i],
takerTokenFillAmounts[i],
takerSellAmounts[i],
signatures[i]
);
}
}
/// @dev Synchronously executes multiple fill orders in a single transaction until total takerTokenFillAmount filled.
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is sold by taker.
/// @param orders Array of orders.
/// @param takerTokenFillAmount Desired amount of takerToken to fill.
/// @param takerSellAmount Desired amount of takerToken to sell.
/// @param signatures Maker's signatures of the orders.
/// @return Total amount of takerTokenFillAmount filled in orders.
function marketFillOrders(
Order[] orders,
uint256 takerTokenFillAmount,
bytes[] signatures)
/// @return Total amount of tokens sold by taker in orders.
function marketSellOrders(
Order[] memory orders,
uint256 takerSellAmount,
bytes[] memory signatures)
public
returns (uint256 totalTakerTokenFilledAmount)
returns (uint256 takerAmountSold)
{
for (uint256 i = 0; i < orders.length; i++) {
require(orders[i].takerTokenAddress == orders[0].takerTokenAddress);
uint256 remainingTakerTokenFillAmount = safeSub(takerTokenFillAmount, totalTakerTokenFilledAmount);
totalTakerTokenFilledAmount = safeAdd(
totalTakerTokenFilledAmount,
uint256 remainingTakerSellAmount = safeSub(takerSellAmount, takerAmountSold);
takerAmountSold = safeAdd(
takerAmountSold,
fillOrder(
orders[i],
remainingTakerTokenFillAmount,
remainingTakerSellAmount,
signatures[i]
)
);
if (totalTakerTokenFilledAmount == takerTokenFillAmount) {
if (takerAmountSold == takerSellAmount) {
break;
}
}
return totalTakerTokenFilledAmount;
return takerAmountSold;
}
/// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction until total takerTokenFillAmount filled.
/// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction until total amount is sold by taker.
/// Returns false if the transaction would otherwise revert.
/// @param orders Array of orders.
/// @param takerTokenFillAmount Desired total amount of takerToken to fill in orders.
/// @param takerSellAmount Desired amount of takerToken to sell.
/// @param signatures Maker's signatures of the orders.
/// @return Total amount of takerTokenFillAmount filled in orders.
function marketFillOrdersNoThrow(
Order[] orders,
uint256 takerTokenFillAmount,
bytes[] signatures)
/// @return Total amount of tokens sold by taker in orders.
function marketSellOrdersNoThrow(
Order[] memory orders,
uint256 takerSellAmount,
bytes[] memory signatures)
public
returns (uint256 totalTakerTokenFilledAmount)
returns (uint256 takerAmountSold)
{
for (uint256 i = 0; i < orders.length; i++) {
require(orders[i].takerTokenAddress == orders[0].takerTokenAddress);
uint256 remainingTakerTokenFillAmount = safeSub(takerTokenFillAmount, totalTakerTokenFilledAmount);
totalTakerTokenFilledAmount = safeAdd(
totalTakerTokenFilledAmount,
uint256 remainingTakerSellAmount = safeSub(takerSellAmount, takerAmountSold);
takerAmountSold = safeAdd(
takerAmountSold,
fillOrderNoThrow(
orders[i],
remainingTakerTokenFillAmount,
remainingTakerSellAmount,
signatures[i]
)
);
if (totalTakerTokenFilledAmount == takerTokenFillAmount) {
if (takerAmountSold == takerSellAmount) {
break;
}
}
return totalTakerTokenFilledAmount;
return takerAmountSold;
}
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
/// @param orders Array of orders.
/// @param takerBuyAmount Desired amount of makerToken to buy.
/// @param signatures Maker's signatures of the orders.
/// @return Total amount of takerTokenFillAmount filled in orders.
function marketBuyOrders(
Order[] memory orders,
uint256 takerBuyAmount,
bytes[] memory signatures)
public
returns (uint256 takerAmountBought)
{
for (uint256 i = 0; i < orders.length; i++) {
require(orders[i].takerTokenAddress == orders[0].takerTokenAddress);
uint256 remainingTakerBuyAmount = safeSub(takerBuyAmount, takerAmountBought);
uint256 takerSellAmount = getPartialAmount(
orders[i].makerBuyAmount,
orders[i].makerSellAmount,
remainingTakerBuyAmount
);
uint256 takerAmountSold = fillOrder(
orders[i],
takerSellAmount,
signatures[i]
);
takerAmountBought = safeAdd(
takerAmountBought,
getPartialAmount(
orders[i].makerSellAmount,
orders[i].makerBuyAmount,
takerAmountSold
)
);
if (takerAmountBought == takerBuyAmount) {
break;
}
}
return takerAmountBought;
}
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
/// Returns false if the transaction would otherwise revert.
/// @param orders Array of orders.
/// @param takerBuyAmount Desired amount of makerToken to fill.
/// @param signatures Maker's signatures of the orders.
/// @return Total amount of takerTokenFillAmount filled in orders.
function marketBuyOrdersNoThrow(
Order[] memory orders,
uint256 takerBuyAmount,
bytes[] memory signatures)
public
returns (uint256 takerAmountBought)
{
for (uint256 i = 0; i < orders.length; i++) {
require(orders[i].takerTokenAddress == orders[0].takerTokenAddress);
uint256 remainingTakerBuyAmount = safeSub(takerBuyAmount, takerAmountBought);
uint256 takerSellAmount = getPartialAmount(
orders[i].makerBuyAmount,
orders[i].makerSellAmount,
remainingTakerBuyAmount
);
uint256 takerAmountSold = fillOrderNoThrow(
orders[i],
takerSellAmount,
signatures[i]
);
takerAmountBought = safeAdd(
takerAmountBought,
getPartialAmount(
orders[i].makerSellAmount,
orders[i].makerBuyAmount,
takerAmountSold
)
);
if (takerAmountBought == takerBuyAmount) {
break;
}
}
return takerAmountBought;
}
/// @dev Synchronously cancels multiple orders in a single transaction.
/// @param orders Array of orders.
function batchCancelOrders(Order[] orders)
function batchCancelOrders(Order[] memory orders)
public
{
for (uint256 i = 0; i < orders.length; i++) {

View File

@@ -22,12 +22,12 @@ export class ExchangeWrapper {
public async fillOrderAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerTokenFillAmount?: BigNumber } = {},
opts: { takerSellAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const params = orderUtils.createFill(signedOrder, opts.takerSellAmount);
const txHash = await this._exchange.fillOrder.sendTransactionAsync(
params.order,
params.takerTokenFillAmount,
params.takerSellAmount,
params.signature,
{ from },
);
@@ -43,12 +43,12 @@ export class ExchangeWrapper {
public async fillOrKillOrderAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerTokenFillAmount?: BigNumber } = {},
opts: { takerSellAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const params = orderUtils.createFill(signedOrder, opts.takerSellAmount);
const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
params.order,
params.takerTokenFillAmount,
params.takerSellAmount,
params.signature,
{ from },
);
@@ -58,12 +58,12 @@ export class ExchangeWrapper {
public async fillOrderNoThrowAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerTokenFillAmount?: BigNumber } = {},
opts: { takerSellAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerTokenFillAmount);
const params = orderUtils.createFill(signedOrder, opts.takerSellAmount);
const txHash = await this._exchange.fillOrderNoThrow.sendTransactionAsync(
params.order,
params.takerTokenFillAmount,
params.takerSellAmount,
params.signature,
{ from },
);
@@ -73,12 +73,12 @@ export class ExchangeWrapper {
public async batchFillOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerTokenFillAmounts?: BigNumber[] } = {},
opts: { takerSellAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
const params = formatters.createBatchFill(orders, opts.takerSellAmounts);
const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
params.orders,
params.takerTokenFillAmounts,
params.takerSellAmounts,
params.signatures,
{ from },
);
@@ -88,12 +88,12 @@ export class ExchangeWrapper {
public async batchFillOrKillOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerTokenFillAmounts?: BigNumber[] } = {},
opts: { takerSellAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
const params = formatters.createBatchFill(orders, opts.takerSellAmounts);
const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
params.orders,
params.takerTokenFillAmounts,
params.takerSellAmounts,
params.signatures,
{ from },
);
@@ -103,42 +103,72 @@ export class ExchangeWrapper {
public async batchFillOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { takerTokenFillAmounts?: BigNumber[] } = {},
opts: { takerSellAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
const params = formatters.createBatchFill(orders, opts.takerSellAmounts);
const txHash = await this._exchange.batchFillOrdersNoThrow.sendTransactionAsync(
params.orders,
params.takerTokenFillAmounts,
params.takerSellAmounts,
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async marketFillOrdersAsync(
public async marketSellOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerTokenFillAmount: BigNumber },
opts: { takerSellAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketFillOrders(orders, opts.takerTokenFillAmount);
const txHash = await this._exchange.marketFillOrders.sendTransactionAsync(
const params = formatters.createMarketSellOrders(orders, opts.takerSellAmount);
const txHash = await this._exchange.marketSellOrders.sendTransactionAsync(
params.orders,
params.takerTokenFillAmount,
params.takerSellAmount,
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async marketFillOrdersNoThrowAsync(
public async marketSellOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { takerTokenFillAmount: BigNumber },
opts: { takerSellAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketFillOrders(orders, opts.takerTokenFillAmount);
const txHash = await this._exchange.marketFillOrdersNoThrow.sendTransactionAsync(
const params = formatters.createMarketSellOrders(orders, opts.takerSellAmount);
const txHash = await this._exchange.marketSellOrdersNoThrow.sendTransactionAsync(
params.orders,
params.takerTokenFillAmount,
params.takerSellAmount,
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async marketBuyOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerBuyAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketBuyOrders(orders, opts.takerBuyAmount);
const txHash = await this._exchange.marketBuyOrders.sendTransactionAsync(
params.orders,
params.takerBuyAmount,
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async marketBuyOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { takerBuyAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketBuyOrders(orders, opts.takerBuyAmount);
const txHash = await this._exchange.marketBuyOrdersNoThrow.sendTransactionAsync(
params.orders,
params.takerBuyAmount,
params.signatures,
{ from },
);
@@ -191,7 +221,7 @@ export class ExchangeWrapper {
);
return partialAmount;
}
public async getFilledTakerTokenAmountAsync(orderHashHex: string): Promise<BigNumber> {
public async getMakerAmountBoughtAsync(orderHashHex: string): Promise<BigNumber> {
const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex));
return filledAmount;
}

View File

@@ -1,78 +1,59 @@
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { BatchCancelOrders, BatchFillOrders, MarketFillOrders, SignedOrder } from './types';
import { orderUtils } from './order_utils';
import { BatchCancelOrders, BatchFillOrders, MarketBuyOrders, MarketSellOrders, SignedOrder } from './types';
export const formatters = {
createBatchFill(signedOrders: SignedOrder[], takerTokenFillAmounts: BigNumber[] = []) {
createBatchFill(signedOrders: SignedOrder[], takerSellAmounts: BigNumber[] = []) {
const batchFill: BatchFillOrders = {
orders: [],
signatures: [],
takerTokenFillAmounts,
takerSellAmounts,
};
_.forEach(signedOrders, signedOrder => {
batchFill.orders.push({
makerAddress: signedOrder.makerAddress,
takerAddress: signedOrder.takerAddress,
makerTokenAddress: signedOrder.makerTokenAddress,
takerTokenAddress: signedOrder.takerTokenAddress,
feeRecipientAddress: signedOrder.feeRecipientAddress,
makerTokenAmount: signedOrder.makerTokenAmount,
takerTokenAmount: signedOrder.takerTokenAmount,
makerFeeAmount: signedOrder.makerFeeAmount,
takerFeeAmount: signedOrder.takerFeeAmount,
expirationTimeSeconds: signedOrder.expirationTimeSeconds,
salt: signedOrder.salt,
});
const orderStruct = orderUtils.getOrderStruct(signedOrder);
batchFill.orders.push(orderStruct);
batchFill.signatures.push(signedOrder.signature);
if (takerTokenFillAmounts.length < signedOrders.length) {
batchFill.takerTokenFillAmounts.push(signedOrder.takerTokenAmount);
if (takerSellAmounts.length < signedOrders.length) {
batchFill.takerSellAmounts.push(signedOrder.makerBuyAmount);
}
});
return batchFill;
},
createMarketFillOrders(signedOrders: SignedOrder[], takerTokenFillAmount: BigNumber) {
const marketFillOrders: MarketFillOrders = {
createMarketSellOrders(signedOrders: SignedOrder[], takerSellAmount: BigNumber) {
const marketSellOrders: MarketSellOrders = {
orders: [],
signatures: [],
takerTokenFillAmount,
takerSellAmount,
};
_.forEach(signedOrders, signedOrder => {
marketFillOrders.orders.push({
makerAddress: signedOrder.makerAddress,
takerAddress: signedOrder.takerAddress,
makerTokenAddress: signedOrder.makerTokenAddress,
takerTokenAddress: signedOrder.takerTokenAddress,
feeRecipientAddress: signedOrder.feeRecipientAddress,
makerTokenAmount: signedOrder.makerTokenAmount,
takerTokenAmount: signedOrder.takerTokenAmount,
makerFeeAmount: signedOrder.makerFeeAmount,
takerFeeAmount: signedOrder.takerFeeAmount,
expirationTimeSeconds: signedOrder.expirationTimeSeconds,
salt: signedOrder.salt,
});
marketFillOrders.signatures.push(signedOrder.signature);
const orderStruct = orderUtils.getOrderStruct(signedOrder);
marketSellOrders.orders.push(orderStruct);
marketSellOrders.signatures.push(signedOrder.signature);
});
return marketFillOrders;
return marketSellOrders;
},
createMarketBuyOrders(signedOrders: SignedOrder[], takerBuyAmount: BigNumber) {
const marketBuyOrders: MarketBuyOrders = {
orders: [],
signatures: [],
takerBuyAmount,
};
_.forEach(signedOrders, signedOrder => {
const orderStruct = orderUtils.getOrderStruct(signedOrder);
marketBuyOrders.orders.push(orderStruct);
marketBuyOrders.signatures.push(signedOrder.signature);
});
return marketBuyOrders;
},
createBatchCancel(signedOrders: SignedOrder[]) {
const batchCancel: BatchCancelOrders = {
orders: [],
};
_.forEach(signedOrders, signedOrder => {
batchCancel.orders.push({
makerAddress: signedOrder.makerAddress,
takerAddress: signedOrder.takerAddress,
makerTokenAddress: signedOrder.makerTokenAddress,
takerTokenAddress: signedOrder.takerTokenAddress,
feeRecipientAddress: signedOrder.feeRecipientAddress,
makerTokenAmount: signedOrder.makerTokenAmount,
takerTokenAmount: signedOrder.takerTokenAmount,
makerFeeAmount: signedOrder.makerFeeAmount,
takerFeeAmount: signedOrder.takerFeeAmount,
expirationTimeSeconds: signedOrder.expirationTimeSeconds,
salt: signedOrder.salt,
});
const orderStruct = orderUtils.getOrderStruct(signedOrder);
batchCancel.orders.push(orderStruct);
});
return batchCancel;
},

View File

@@ -7,10 +7,10 @@ import { crypto } from './crypto';
import { OrderStruct, SignatureType, SignedOrder, UnsignedOrder } from './types';
export const orderUtils = {
createFill: (signedOrder: SignedOrder, takerTokenFillAmount?: BigNumber) => {
createFill: (signedOrder: SignedOrder, takerSellAmount?: BigNumber) => {
const fill = {
order: orderUtils.getOrderStruct(signedOrder),
takerTokenFillAmount: takerTokenFillAmount || signedOrder.takerTokenAmount,
takerSellAmount: takerSellAmount || signedOrder.makerBuyAmount,
signature: signedOrder.signature,
};
return fill;
@@ -18,7 +18,7 @@ export const orderUtils = {
createCancel(signedOrder: SignedOrder, takerTokenCancelAmount?: BigNumber) {
const cancel = {
order: orderUtils.getOrderStruct(signedOrder),
takerTokenCancelAmount: takerTokenCancelAmount || signedOrder.takerTokenAmount,
takerTokenCancelAmount: takerTokenCancelAmount || signedOrder.makerBuyAmount,
};
return cancel;
},
@@ -29,10 +29,10 @@ export const orderUtils = {
makerTokenAddress: signedOrder.makerTokenAddress,
takerTokenAddress: signedOrder.takerTokenAddress,
feeRecipientAddress: signedOrder.feeRecipientAddress,
makerTokenAmount: signedOrder.makerTokenAmount,
takerTokenAmount: signedOrder.takerTokenAmount,
makerFeeAmount: signedOrder.makerFeeAmount,
takerFeeAmount: signedOrder.takerFeeAmount,
makerSellAmount: signedOrder.makerSellAmount,
makerBuyAmount: signedOrder.makerBuyAmount,
makerFee: signedOrder.makerFee,
takerFee: signedOrder.takerFee,
expirationTimeSeconds: signedOrder.expirationTimeSeconds,
salt: signedOrder.salt,
};
@@ -46,10 +46,10 @@ export const orderUtils = {
'address makerTokenAddress',
'address takerTokenAddress',
'address feeRecipientAddress',
'uint256 makerTokenAmount',
'uint256 takerTokenAmount',
'uint256 makerFeeAmount',
'uint256 takerFeeAmount',
'uint256 makerSellAmount',
'uint256 makerBuyAmount',
'uint256 makerFee',
'uint256 takerFee',
'uint256 expirationTimeSeconds',
'uint256 salt',
]);
@@ -60,10 +60,10 @@ export const orderUtils = {
order.makerTokenAddress,
order.takerTokenAddress,
order.feeRecipientAddress,
order.makerTokenAmount,
order.takerTokenAmount,
order.makerFeeAmount,
order.takerFeeAmount,
order.makerSellAmount,
order.makerBuyAmount,
order.makerFee,
order.takerFee,
order.expirationTimeSeconds,
order.salt,
]);

View File

@@ -14,13 +14,19 @@ export interface SubmissionContractEventArgs {
export interface BatchFillOrders {
orders: OrderStruct[];
signatures: string[];
takerTokenFillAmounts: BigNumber[];
takerSellAmounts: BigNumber[];
}
export interface MarketFillOrders {
export interface MarketSellOrders {
orders: OrderStruct[];
signatures: string[];
takerTokenFillAmount: BigNumber;
takerSellAmount: BigNumber;
}
export interface MarketBuyOrders {
orders: OrderStruct[];
signatures: string[];
takerBuyAmount: BigNumber;
}
export interface BatchCancelOrders {
@@ -37,10 +43,10 @@ export interface DefaultOrderParams {
feeRecipientAddress: string;
makerTokenAddress: string;
takerTokenAddress: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFeeAmount: BigNumber;
takerFeeAmount: BigNumber;
makerSellAmount: BigNumber;
makerBuyAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
}
export interface TransactionDataParams {
@@ -122,10 +128,10 @@ export interface OrderStruct {
makerTokenAddress: string;
takerTokenAddress: string;
feeRecipientAddress: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFeeAmount: BigNumber;
takerFeeAmount: BigNumber;
makerSellAmount: BigNumber;
makerBuyAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
expirationTimeSeconds: BigNumber;
salt: BigNumber;
}

View File

@@ -19,7 +19,6 @@ import { Balances } from '../../src/utils/balances';
import { constants } from '../../src/utils/constants';
import { crypto } from '../../src/utils/crypto';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { LogDecoder } from '../../src/utils/log_decoder';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { BalancesByOwner, ContractName, ExchangeContractErrs, SignatureType, SignedOrder } from '../../src/utils/types';
@@ -30,7 +29,6 @@ import { provider, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const logDecoder = new LogDecoder(constants.TESTRPC_NETWORK_ID);
describe('Exchange', () => {
let makerAddress: string;
@@ -90,10 +88,10 @@ describe('Exchange', () => {
feeRecipientAddress,
makerTokenAddress: rep.address,
takerTokenAddress: dgd.address,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[0];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -145,80 +143,80 @@ describe('Exchange', () => {
it('should create an unfillable order', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: new BigNumber(1001),
takerTokenAmount: new BigNumber(3),
makerSellAmount: new BigNumber(1001),
makerBuyAmount: new BigNumber(3),
});
const filledTakerTokenAmountBefore = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtBefore = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0);
expect(makerAmountBoughtBefore).to.be.bignumber.equal(0);
const fillTakerTokenAmount1 = new BigNumber(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: fillTakerTokenAmount1,
takerSellAmount: fillTakerTokenAmount1,
});
const filledTakerTokenAmountAfter1 = await exWrapper.getFilledTakerTokenAmountAsync(
const filledTakerTokenAmountAfter1 = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountAfter1).to.be.bignumber.equal(fillTakerTokenAmount1);
const fillTakerTokenAmount2 = new BigNumber(1);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: fillTakerTokenAmount2,
takerSellAmount: fillTakerTokenAmount2,
});
const filledTakerTokenAmountAfter2 = await exWrapper.getFilledTakerTokenAmountAsync(
const filledTakerTokenAmountAfter2 = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountAfter2).to.be.bignumber.equal(filledTakerTokenAmountAfter1);
});
it('should transfer the correct amounts when makerTokenAmount === takerTokenAmount', async () => {
it('should transfer the correct amounts when makerSellAmount === makerBuyAmount', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
});
const filledTakerTokenAmountBefore = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtBefore = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0);
expect(makerAmountBoughtBefore).to.be.bignumber.equal(0);
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerTokenFillAmount });
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerSellAmount });
const filledTakerTokenAmountAfter = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtAfter = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(takerTokenFillAmount);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerSellAmount);
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeePaid = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeePaid = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFeePaid = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFeePaid = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeePaid),
@@ -228,50 +226,50 @@ describe('Exchange', () => {
);
});
it('should transfer the correct amounts when makerTokenAmount > takerTokenAmount', async () => {
it('should transfer the correct amounts when makerSellAmount > makerBuyAmount', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
});
const filledTakerTokenAmountBefore = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtBefore = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0);
expect(makerAmountBoughtBefore).to.be.bignumber.equal(0);
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerTokenFillAmount });
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerSellAmount });
const filledTakerTokenAmountAfter = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtAfter = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(takerTokenFillAmount);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerSellAmount);
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeePaid = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeePaid = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFeePaid = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFeePaid = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeePaid),
@@ -281,50 +279,50 @@ describe('Exchange', () => {
);
});
it('should transfer the correct amounts when makerTokenAmount < takerTokenAmount', async () => {
it('should transfer the correct amounts when makerSellAmount < makerBuyAmount', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const filledTakerTokenAmountBefore = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtBefore = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0);
expect(makerAmountBoughtBefore).to.be.bignumber.equal(0);
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerTokenFillAmount });
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerSellAmount });
const filledTakerTokenAmountAfter = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtAfter = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(takerTokenFillAmount);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerSellAmount);
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeePaid = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeePaid = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFeePaid = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFeePaid = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeePaid),
@@ -337,49 +335,49 @@ describe('Exchange', () => {
it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
signedOrder = orderFactory.newSignedOrder({
takerAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const filledTakerTokenAmountBefore = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtBefore = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0);
expect(makerAmountBoughtBefore).to.be.bignumber.equal(0);
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerTokenFillAmount });
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerSellAmount });
const filledTakerTokenAmountAfter = await exWrapper.getFilledTakerTokenAmountAsync(
const makerAmountBoughtAfter = await exWrapper.getMakerAmountBoughtAsync(
orderUtils.getOrderHashHex(signedOrder),
);
const expectedFillAmountTAfter = takerTokenFillAmount.add(filledTakerTokenAmountBefore);
expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(expectedFillAmountTAfter);
const expectedMakerAmountBoughtAfter = takerSellAmount.add(makerAmountBoughtBefore);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(expectedMakerAmountBoughtAfter);
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeePaid = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeePaid = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFeePaid = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFeePaid = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeePaid),
@@ -389,69 +387,63 @@ describe('Exchange', () => {
);
});
it('should fill remaining value if takerTokenFillAmount > remaining takerTokenAmount', async () => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerTokenFillAmount });
it('should fill remaining value if takerSellAmount > remaining makerBuyAmount', async () => {
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, { takerSellAmount });
const res = await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: signedOrder.takerTokenAmount,
takerSellAmount: signedOrder.makerBuyAmount,
});
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogFillContractEventArgs>;
expect(log.args.takerTokenFilledAmount).to.be.bignumber.equal(
signedOrder.takerTokenAmount.minus(takerTokenFillAmount),
);
const log = res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>;
expect(log.args.makerAmountBought).to.be.bignumber.equal(signedOrder.makerBuyAmount.minus(takerSellAmount));
const newBalances = await dmyBalances.getAsync();
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(signedOrder.makerTokenAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(signedOrder.makerSellAmount),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(signedOrder.takerTokenAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(signedOrder.makerBuyAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(signedOrder.makerFeeAmount),
balances[makerAddress][zrx.address].minus(signedOrder.makerFee),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(signedOrder.takerTokenAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(signedOrder.makerBuyAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(signedOrder.makerTokenAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(signedOrder.makerSellAmount),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(signedOrder.takerFeeAmount),
balances[takerAddress][zrx.address].minus(signedOrder.takerFee),
);
expect(newBalances[feeRecipientAddress][zrx.address]).to.be.bignumber.equal(
balances[feeRecipientAddress][zrx.address].add(
signedOrder.makerFeeAmount.add(signedOrder.takerFeeAmount),
),
balances[feeRecipientAddress][zrx.address].add(signedOrder.makerFee.add(signedOrder.takerFee)),
);
});
it('should log 1 event with the correct arguments when order has a feeRecipient', async () => {
const divisor = 2;
const res = await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: signedOrder.takerTokenAmount.div(divisor),
takerSellAmount: signedOrder.makerBuyAmount.div(divisor),
});
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogFillContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>;
const logArgs = log.args;
const expectedFilledMakerTokenAmount = signedOrder.makerTokenAmount.div(divisor);
const expectedFilledTakerTokenAmount = signedOrder.takerTokenAmount.div(divisor);
const expectedFeeMPaid = signedOrder.makerFeeAmount.div(divisor);
const expectedFeeTPaid = signedOrder.takerFeeAmount.div(divisor);
const tokensHashBuff = crypto.solSHA3([signedOrder.makerTokenAddress, signedOrder.takerTokenAddress]);
const expectedTokens = ethUtil.bufferToHex(tokensHashBuff);
const expectedFilledMakerTokenAmount = signedOrder.makerSellAmount.div(divisor);
const expectedFilledTakerTokenAmount = signedOrder.makerBuyAmount.div(divisor);
const expectedFeeMPaid = signedOrder.makerFee.div(divisor);
const expectedFeeTPaid = signedOrder.takerFee.div(divisor);
expect(signedOrder.makerAddress).to.be.equal(logArgs.makerAddress);
expect(takerAddress).to.be.equal(logArgs.takerAddress);
expect(signedOrder.feeRecipientAddress).to.be.equal(logArgs.feeRecipientAddress);
expect(signedOrder.makerTokenAddress).to.be.equal(logArgs.makerTokenAddress);
expect(signedOrder.takerTokenAddress).to.be.equal(logArgs.takerTokenAddress);
expect(expectedFilledMakerTokenAmount).to.be.bignumber.equal(logArgs.makerTokenFilledAmount);
expect(expectedFilledTakerTokenAmount).to.be.bignumber.equal(logArgs.takerTokenFilledAmount);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeeAmountPaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeeAmountPaid);
expect(expectedFilledMakerTokenAmount).to.be.bignumber.equal(logArgs.makerAmountSold);
expect(expectedFilledTakerTokenAmount).to.be.bignumber.equal(logArgs.makerAmountBought);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeePaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeePaid);
expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
@@ -461,43 +453,41 @@ describe('Exchange', () => {
});
const divisor = 2;
const res = await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: signedOrder.takerTokenAmount.div(divisor),
takerSellAmount: signedOrder.makerBuyAmount.div(divisor),
});
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogFillContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>;
const logArgs = log.args;
const expectedFilledMakerTokenAmount = signedOrder.makerTokenAmount.div(divisor);
const expectedFilledTakerTokenAmount = signedOrder.takerTokenAmount.div(divisor);
const expectedFilledMakerTokenAmount = signedOrder.makerSellAmount.div(divisor);
const expectedFilledTakerTokenAmount = signedOrder.makerBuyAmount.div(divisor);
const expectedFeeMPaid = new BigNumber(0);
const expectedFeeTPaid = new BigNumber(0);
const tokensHashBuff = crypto.solSHA3([signedOrder.makerTokenAddress, signedOrder.takerTokenAddress]);
const expectedTokens = ethUtil.bufferToHex(tokensHashBuff);
expect(signedOrder.makerAddress).to.be.equal(logArgs.makerAddress);
expect(takerAddress).to.be.equal(logArgs.takerAddress);
expect(signedOrder.feeRecipientAddress).to.be.equal(logArgs.feeRecipientAddress);
expect(signedOrder.makerTokenAddress).to.be.equal(logArgs.makerTokenAddress);
expect(signedOrder.takerTokenAddress).to.be.equal(logArgs.takerTokenAddress);
expect(expectedFilledMakerTokenAmount).to.be.bignumber.equal(logArgs.makerTokenFilledAmount);
expect(expectedFilledTakerTokenAmount).to.be.bignumber.equal(logArgs.takerTokenFilledAmount);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeeAmountPaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeeAmountPaid);
expect(expectedFilledMakerTokenAmount).to.be.bignumber.equal(logArgs.makerAmountSold);
expect(expectedFilledTakerTokenAmount).to.be.bignumber.equal(logArgs.makerAmountBought);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeePaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeePaid);
expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
it('should throw when taker is specified and order is claimed by other', async () => {
signedOrder = orderFactory.newSignedOrder({
takerAddress: feeRecipientAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if signature is invalid', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(10), 18),
});
const invalidR = ethUtil.sha3('invalidR');
@@ -509,35 +499,9 @@ describe('Exchange', () => {
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if makerTokenAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: new BigNumber(0),
});
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if takerTokenAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
takerTokenAmount: new BigNumber(0),
});
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if takerTokenFillAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder();
return expect(
exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: new BigNumber(0),
}),
).to.be.rejectedWith(constants.REVERT);
});
it('should throw if maker balances are too low to fill order', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
});
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
@@ -545,7 +509,7 @@ describe('Exchange', () => {
it('should throw if taker balances are too low to fill order', async () => {
signedOrder = orderFactory.newSignedOrder({
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
});
return expect(exWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
@@ -588,7 +552,7 @@ describe('Exchange', () => {
const res = await exWrapper.fillOrderAsync(signedOrder, takerAddress);
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogErrorContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
const errCode = log.args.errorId;
expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED);
});
@@ -599,7 +563,7 @@ describe('Exchange', () => {
const res = await exWrapper.fillOrderAsync(signedOrder, takerAddress);
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogErrorContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
const errCode = log.args.errorId;
expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_FULLY_FILLED);
});
@@ -615,26 +579,10 @@ describe('Exchange', () => {
return expect(exWrapper.cancelOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if makerTokenAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: new BigNumber(0),
});
return expect(exWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should throw if takerTokenAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
takerTokenAmount: new BigNumber(0),
});
return expect(exWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith(constants.REVERT);
});
it('should be able to cancel a full order', async () => {
await exWrapper.cancelOrderAsync(signedOrder, makerAddress);
await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: signedOrder.takerTokenAmount.div(2),
takerSellAmount: signedOrder.makerBuyAmount.div(2),
});
const newBalances = await dmyBalances.getAsync();
@@ -646,7 +594,7 @@ describe('Exchange', () => {
const res = await exWrapper.cancelOrderAsync(signedOrder, makerAddress);
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogCancelContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogCancelContractEventArgs>;
const logArgs = log.args;
expect(signedOrder.makerAddress).to.be.equal(logArgs.makerAddress);
@@ -661,7 +609,7 @@ describe('Exchange', () => {
const res = await exWrapper.cancelOrderAsync(signedOrder, makerAddress);
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogErrorContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
const errCode = log.args.errorId;
expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_CANCELLED);
});
@@ -673,7 +621,7 @@ describe('Exchange', () => {
const res = await exWrapper.cancelOrderAsync(signedOrder, makerAddress);
expect(res.logs).to.have.length(1);
const log = logDecoder.decodeLogOrThrow(res.logs[0]) as LogWithDecodedArgs<LogErrorContractEventArgs>;
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
const errCode = log.args.errorId;
expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED);
});
@@ -707,33 +655,33 @@ describe('Exchange', () => {
balances = await dmyBalances.getAsync();
const signedOrders = await Promise.all([
orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(9), 18),
salt: new BigNumber(0),
}),
orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(79), 18),
salt: new BigNumber(1),
}),
orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(979), 18),
salt: new BigNumber(2),
}),
orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(7979), 18),
salt: new BigNumber(3),
}),
]);
await exWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress);
const newBalances = await dmyBalances.getAsync();
const fillMakerTokenAmount = signedOrders[2].makerTokenAmount.add(signedOrders[3].makerTokenAmount);
const fillTakerTokenAmount = signedOrders[2].takerTokenAmount.add(signedOrders[3].takerTokenAmount);
const makerFeeAmount = signedOrders[2].makerFeeAmount.add(signedOrders[3].makerFeeAmount);
const takerFeeAmount = signedOrders[2].takerFeeAmount.add(signedOrders[3].takerFeeAmount);
const fillMakerTokenAmount = signedOrders[2].makerSellAmount.add(signedOrders[3].makerSellAmount);
const fillTakerTokenAmount = signedOrders[2].makerBuyAmount.add(signedOrders[3].makerBuyAmount);
const makerFee = signedOrders[2].makerFee.add(signedOrders[3].makerFee);
const takerFee = signedOrders[2].takerFee.add(signedOrders[3].takerFee);
expect(newBalances[makerAddress][signedOrders[3].makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrders[3].makerTokenAddress].minus(fillMakerTokenAmount),
);
@@ -741,7 +689,7 @@ describe('Exchange', () => {
balances[makerAddress][signedOrders[3].takerTokenAddress].add(fillTakerTokenAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeeAmount),
balances[makerAddress][zrx.address].minus(makerFee),
);
expect(newBalances[takerAddress][signedOrders[3].takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrders[3].takerTokenAddress].minus(fillTakerTokenAmount),
@@ -750,10 +698,10 @@ describe('Exchange', () => {
balances[takerAddress][signedOrders[3].makerTokenAddress].add(fillMakerTokenAmount),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeeAmount),
balances[takerAddress][zrx.address].minus(takerFee),
);
expect(newBalances[feeRecipientAddress][zrx.address]).to.be.bignumber.equal(
balances[feeRecipientAddress][zrx.address].add(makerFeeAmount.add(takerFeeAmount)),
balances[feeRecipientAddress][zrx.address].add(makerFee.add(takerFee)),
);
});
});

View File

@@ -52,10 +52,10 @@ describe('Exchange', () => {
feeRecipientAddress,
makerTokenAddress: rep.address,
takerTokenAddress: dgd.address,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[0];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);

View File

@@ -85,10 +85,10 @@ describe('Exchange', () => {
feeRecipientAddress,
makerTokenAddress: rep.address,
takerTokenAddress: dgd.address,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFeeAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[0];
@@ -119,45 +119,45 @@ describe('Exchange', () => {
describe('fillOrKillOrder', () => {
it('should transfer the correct amounts', async () => {
const signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrKillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount,
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeeAmount = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeeAmount = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeeAmount),
balances[makerAddress][zrx.address].minus(makerFee),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeeAmount),
balances[takerAddress][zrx.address].minus(takerFee),
);
expect(newBalances[feeRecipientAddress][zrx.address]).to.be.bignumber.equal(
balances[feeRecipientAddress][zrx.address].add(makerFeeAmount.add(takerFeeAmount)),
balances[feeRecipientAddress][zrx.address].add(makerFee.add(takerFee)),
);
});
@@ -171,11 +171,11 @@ describe('Exchange', () => {
);
});
it('should throw if entire takerTokenFillAmount not filled', async () => {
it('should throw if entire takerSellAmount not filled', async () => {
const signedOrder = orderFactory.newSignedOrder();
await exWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerTokenFillAmount: signedOrder.takerTokenAmount.div(2),
takerSellAmount: signedOrder.makerBuyAmount.div(2),
});
return expect(exWrapper.fillOrKillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
@@ -187,51 +187,51 @@ describe('Exchange', () => {
describe('fillOrderNoThrow', () => {
it('should transfer the correct amounts', async () => {
const signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, {
takerTokenFillAmount,
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeeAmount = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeeAmount = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
expect(newBalances[makerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrder.makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrder.takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrder.takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFeeAmount),
balances[makerAddress][zrx.address].minus(makerFee),
);
expect(newBalances[takerAddress][signedOrder.takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrder.takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrder.makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrder.makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrder.makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFeeAmount),
balances[takerAddress][zrx.address].minus(takerFee),
);
expect(newBalances[feeRecipientAddress][zrx.address]).to.be.bignumber.equal(
balances[feeRecipientAddress][zrx.address].add(makerFeeAmount.add(takerFeeAmount)),
balances[feeRecipientAddress][zrx.address].add(makerFee.add(takerFee)),
);
});
it('should not change balances if maker balances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
makerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
@@ -241,7 +241,7 @@ describe('Exchange', () => {
it('should not change balances if taker balances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder({
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
makerBuyAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
@@ -277,48 +277,48 @@ describe('Exchange', () => {
expect(newBalances).to.be.deep.equal(balances);
});
it('should not change balances if makerTokenAddress is ZRX, makerTokenAmount + makerFee > maker balance', async () => {
it('should not change balances if makerTokenAddress is ZRX, makerSellAmount + makerFee > maker balance', async () => {
const makerZRXBalance = new BigNumber(balances[makerAddress][zrx.address]);
const signedOrder = orderFactory.newSignedOrder({
makerTokenAddress: zrx.address,
makerTokenAmount: makerZRXBalance,
makerFeeAmount: new BigNumber(1),
makerSellAmount: makerZRXBalance,
makerFee: new BigNumber(1),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should not change balances if makerTokenAddress is ZRX, makerTokenAmount + makerFee > maker allowance', async () => {
it('should not change balances if makerTokenAddress is ZRX, makerSellAmount + makerFee > maker allowance', async () => {
const makerZRXAllowance = await zrx.allowance.callAsync(makerAddress, tokenTransferProxy.address);
const signedOrder = orderFactory.newSignedOrder({
makerTokenAddress: zrx.address,
makerTokenAmount: new BigNumber(makerZRXAllowance),
makerFeeAmount: new BigNumber(1),
makerSellAmount: new BigNumber(makerZRXAllowance),
makerFee: new BigNumber(1),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should not change balances if takerTokenAddress is ZRX, takerTokenAmount + takerFee > taker balance', async () => {
it('should not change balances if takerTokenAddress is ZRX, makerBuyAmount + takerFee > taker balance', async () => {
const takerZRXBalance = new BigNumber(balances[takerAddress][zrx.address]);
const signedOrder = orderFactory.newSignedOrder({
takerTokenAddress: zrx.address,
takerTokenAmount: takerZRXBalance,
takerFeeAmount: new BigNumber(1),
makerBuyAmount: takerZRXBalance,
takerFee: new BigNumber(1),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should not change balances if takerTokenAddress is ZRX, takerTokenAmount + takerFee > taker allowance', async () => {
it('should not change balances if takerTokenAddress is ZRX, makerBuyAmount + takerFee > taker allowance', async () => {
const takerZRXAllowance = await zrx.allowance.callAsync(takerAddress, tokenTransferProxy.address);
const signedOrder = orderFactory.newSignedOrder({
takerTokenAddress: zrx.address,
takerTokenAmount: new BigNumber(takerZRXAllowance),
takerFeeAmount: new BigNumber(1),
makerBuyAmount: new BigNumber(takerZRXAllowance),
takerFee: new BigNumber(1),
});
await exWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await dmyBalances.getAsync();
@@ -338,42 +338,42 @@ describe('Exchange', () => {
describe('batchFillOrders', () => {
it('should transfer the correct amounts', async () => {
const takerTokenFillAmounts: BigNumber[] = [];
const takerSellAmounts: BigNumber[] = [];
const makerTokenAddress = rep.address;
const takerTokenAddress = dgd.address;
_.forEach(signedOrders, signedOrder => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeeAmount = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeeAmount = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
takerTokenFillAmounts.push(takerTokenFillAmount);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
takerSellAmounts.push(takerSellAmount);
balances[makerAddress][makerTokenAddress] = balances[makerAddress][makerTokenAddress].minus(
makerTokenFillAmount,
makerAmountSold,
);
balances[makerAddress][takerTokenAddress] = balances[makerAddress][takerTokenAddress].add(
takerTokenFillAmount,
takerSellAmount,
);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFeeAmount);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFee);
balances[takerAddress][makerTokenAddress] = balances[takerAddress][makerTokenAddress].add(
makerTokenFillAmount,
makerAmountSold,
);
balances[takerAddress][takerTokenAddress] = balances[takerAddress][takerTokenAddress].minus(
takerTokenFillAmount,
takerSellAmount,
);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFeeAmount);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFee);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
makerFeeAmount.add(takerFeeAmount),
makerFee.add(takerFee),
);
});
await exWrapper.batchFillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmounts,
takerSellAmounts,
});
const newBalances = await dmyBalances.getAsync();
@@ -383,33 +383,33 @@ describe('Exchange', () => {
describe('batchFillOrKillOrders', () => {
it('should transfer the correct amounts', async () => {
const takerTokenFillAmounts: BigNumber[] = [];
const takerSellAmounts: BigNumber[] = [];
const makerTokenAddress = rep.address;
const takerTokenAddress = dgd.address;
_.forEach(signedOrders, signedOrder => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFee = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFee = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
takerTokenFillAmounts.push(takerTokenFillAmount);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
takerSellAmounts.push(takerSellAmount);
balances[makerAddress][makerTokenAddress] = balances[makerAddress][makerTokenAddress].minus(
makerTokenFillAmount,
makerAmountSold,
);
balances[makerAddress][takerTokenAddress] = balances[makerAddress][takerTokenAddress].add(
takerTokenFillAmount,
takerSellAmount,
);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFee);
balances[takerAddress][makerTokenAddress] = balances[takerAddress][makerTokenAddress].add(
makerTokenFillAmount,
makerAmountSold,
);
balances[takerAddress][takerTokenAddress] = balances[takerAddress][takerTokenAddress].minus(
takerTokenFillAmount,
takerSellAmount,
);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFee);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
@@ -418,7 +418,7 @@ describe('Exchange', () => {
});
await exWrapper.batchFillOrKillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmounts,
takerSellAmounts,
});
const newBalances = await dmyBalances.getAsync();
@@ -426,17 +426,17 @@ describe('Exchange', () => {
});
it('should throw if a single signedOrder does not fill the expected amount', async () => {
const takerTokenFillAmounts: BigNumber[] = [];
const takerSellAmounts: BigNumber[] = [];
_.forEach(signedOrders, signedOrder => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
takerTokenFillAmounts.push(takerTokenFillAmount);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
takerSellAmounts.push(takerSellAmount);
});
await exWrapper.fillOrKillOrderAsync(signedOrders[0], takerAddress);
return expect(
exWrapper.batchFillOrKillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmounts,
takerSellAmounts,
}),
).to.be.rejectedWith(constants.REVERT);
});
@@ -444,42 +444,42 @@ describe('Exchange', () => {
describe('batchFillOrdersNoThrow', async () => {
it('should transfer the correct amounts', async () => {
const takerTokenFillAmounts: BigNumber[] = [];
const takerSellAmounts: BigNumber[] = [];
const makerTokenAddress = rep.address;
const takerTokenAddress = dgd.address;
_.forEach(signedOrders, signedOrder => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeeAmount = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeeAmount = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
takerTokenFillAmounts.push(takerTokenFillAmount);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
takerSellAmounts.push(takerSellAmount);
balances[makerAddress][makerTokenAddress] = balances[makerAddress][makerTokenAddress].minus(
makerTokenFillAmount,
makerAmountSold,
);
balances[makerAddress][takerTokenAddress] = balances[makerAddress][takerTokenAddress].add(
takerTokenFillAmount,
takerSellAmount,
);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFeeAmount);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFee);
balances[takerAddress][makerTokenAddress] = balances[takerAddress][makerTokenAddress].add(
makerTokenFillAmount,
makerAmountSold,
);
balances[takerAddress][takerTokenAddress] = balances[takerAddress][takerTokenAddress].minus(
takerTokenFillAmount,
takerSellAmount,
);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFeeAmount);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFee);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
makerFeeAmount.add(takerFeeAmount),
makerFee.add(takerFee),
);
});
await exWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress, {
takerTokenFillAmounts,
takerSellAmounts,
});
const newBalances = await dmyBalances.getAsync();
@@ -487,7 +487,7 @@ describe('Exchange', () => {
});
it('should not throw if an order is invalid and fill the remaining orders', async () => {
const takerTokenFillAmounts: BigNumber[] = [];
const takerSellAmounts: BigNumber[] = [];
const makerTokenAddress = rep.address;
const takerTokenAddress = dgd.address;
@@ -497,41 +497,41 @@ describe('Exchange', () => {
};
const validOrders = signedOrders.slice(1);
takerTokenFillAmounts.push(invalidOrder.takerTokenAmount.div(2));
takerSellAmounts.push(invalidOrder.makerBuyAmount.div(2));
_.forEach(validOrders, signedOrder => {
const takerTokenFillAmount = signedOrder.takerTokenAmount.div(2);
const makerTokenFillAmount = takerTokenFillAmount
.times(signedOrder.makerTokenAmount)
.dividedToIntegerBy(signedOrder.takerTokenAmount);
const makerFeeAmount = signedOrder.makerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
const takerFeeAmount = signedOrder.takerFeeAmount
.times(makerTokenFillAmount)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
takerTokenFillAmounts.push(takerTokenFillAmount);
const takerSellAmount = signedOrder.makerBuyAmount.div(2);
const makerAmountSold = takerSellAmount
.times(signedOrder.makerSellAmount)
.dividedToIntegerBy(signedOrder.makerBuyAmount);
const makerFee = signedOrder.makerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
const takerFee = signedOrder.takerFee
.times(makerAmountSold)
.dividedToIntegerBy(signedOrder.makerSellAmount);
takerSellAmounts.push(takerSellAmount);
balances[makerAddress][makerTokenAddress] = balances[makerAddress][makerTokenAddress].minus(
makerTokenFillAmount,
makerAmountSold,
);
balances[makerAddress][takerTokenAddress] = balances[makerAddress][takerTokenAddress].add(
takerTokenFillAmount,
takerSellAmount,
);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFeeAmount);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(makerFee);
balances[takerAddress][makerTokenAddress] = balances[takerAddress][makerTokenAddress].add(
makerTokenFillAmount,
makerAmountSold,
);
balances[takerAddress][takerTokenAddress] = balances[takerAddress][takerTokenAddress].minus(
takerTokenFillAmount,
takerSellAmount,
);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFeeAmount);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(takerFee);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
makerFeeAmount.add(takerFeeAmount),
makerFee.add(takerFee),
);
});
const newOrders = [invalidOrder, ...validOrders];
await exWrapper.batchFillOrdersNoThrowAsync(newOrders, takerAddress, {
takerTokenFillAmounts,
takerSellAmounts,
});
const newBalances = await dmyBalances.getAsync();
@@ -540,39 +540,33 @@ describe('Exchange', () => {
});
describe('marketFillOrders', () => {
it('should stop when the entire takerTokenFillAmount is filled', async () => {
const takerTokenFillAmount = signedOrders[0].takerTokenAmount.plus(
signedOrders[1].takerTokenAmount.div(2),
);
await exWrapper.marketFillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmount,
it('should stop when the entire takerSellAmount is filled', async () => {
const takerSellAmount = signedOrders[0].makerBuyAmount.plus(signedOrders[1].makerBuyAmount.div(2));
await exWrapper.marketSellOrdersAsync(signedOrders, takerAddress, {
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = signedOrders[0].makerTokenAmount.add(
signedOrders[1].makerTokenAmount.dividedToIntegerBy(2),
);
const makerFee = signedOrders[0].makerFeeAmount.add(
signedOrders[1].makerFeeAmount.dividedToIntegerBy(2),
);
const takerFee = signedOrders[0].takerFeeAmount.add(
signedOrders[1].takerFeeAmount.dividedToIntegerBy(2),
const makerAmountSold = signedOrders[0].makerSellAmount.add(
signedOrders[1].makerSellAmount.dividedToIntegerBy(2),
);
const makerFee = signedOrders[0].makerFee.add(signedOrders[1].makerFee.dividedToIntegerBy(2));
const takerFee = signedOrders[0].takerFee.add(signedOrders[1].takerFee.dividedToIntegerBy(2));
expect(newBalances[makerAddress][signedOrders[0].makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrders[0].makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrders[0].makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrders[0].takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrders[0].takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrders[0].takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFee),
);
expect(newBalances[takerAddress][signedOrders[0].takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrders[0].takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrders[0].takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrders[0].makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrders[0].makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrders[0].makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFee),
@@ -582,33 +576,33 @@ describe('Exchange', () => {
);
});
it('should fill all signedOrders if cannot fill entire takerTokenFillAmount', async () => {
const takerTokenFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
it('should fill all signedOrders if cannot fill entire takerSellAmount', async () => {
const takerSellAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
_.forEach(signedOrders, signedOrder => {
balances[makerAddress][signedOrder.makerTokenAddress] = balances[makerAddress][
signedOrder.makerTokenAddress
].minus(signedOrder.makerTokenAmount);
].minus(signedOrder.makerSellAmount);
balances[makerAddress][signedOrder.takerTokenAddress] = balances[makerAddress][
signedOrder.takerTokenAddress
].add(signedOrder.takerTokenAmount);
].add(signedOrder.makerBuyAmount);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(
signedOrder.makerFeeAmount,
signedOrder.makerFee,
);
balances[takerAddress][signedOrder.makerTokenAddress] = balances[takerAddress][
signedOrder.makerTokenAddress
].add(signedOrder.makerTokenAmount);
].add(signedOrder.makerSellAmount);
balances[takerAddress][signedOrder.takerTokenAddress] = balances[takerAddress][
signedOrder.takerTokenAddress
].minus(signedOrder.takerTokenAmount);
].minus(signedOrder.makerBuyAmount);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(
signedOrder.takerFeeAmount,
signedOrder.takerFee,
);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
signedOrder.makerFeeAmount.add(signedOrder.takerFeeAmount),
signedOrder.makerFee.add(signedOrder.takerFee),
);
});
await exWrapper.marketFillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmount,
await exWrapper.marketSellOrdersAsync(signedOrders, takerAddress, {
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
@@ -623,47 +617,41 @@ describe('Exchange', () => {
];
return expect(
exWrapper.marketFillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18),
exWrapper.marketSellOrdersAsync(signedOrders, takerAddress, {
takerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18),
}),
).to.be.rejectedWith(constants.REVERT);
});
});
describe('marketFillOrdersNoThrow', () => {
it('should stop when the entire takerTokenFillAmount is filled', async () => {
const takerTokenFillAmount = signedOrders[0].takerTokenAmount.plus(
signedOrders[1].takerTokenAmount.div(2),
);
await exWrapper.marketFillOrdersNoThrowAsync(signedOrders, takerAddress, {
takerTokenFillAmount,
it('should stop when the entire takerSellAmount is filled', async () => {
const takerSellAmount = signedOrders[0].makerBuyAmount.plus(signedOrders[1].makerBuyAmount.div(2));
await exWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
const makerTokenFillAmount = signedOrders[0].makerTokenAmount.add(
signedOrders[1].makerTokenAmount.dividedToIntegerBy(2),
);
const makerFee = signedOrders[0].makerFeeAmount.add(
signedOrders[1].makerFeeAmount.dividedToIntegerBy(2),
);
const takerFee = signedOrders[0].takerFeeAmount.add(
signedOrders[1].takerFeeAmount.dividedToIntegerBy(2),
const makerAmountSold = signedOrders[0].makerSellAmount.add(
signedOrders[1].makerSellAmount.dividedToIntegerBy(2),
);
const makerFee = signedOrders[0].makerFee.add(signedOrders[1].makerFee.dividedToIntegerBy(2));
const takerFee = signedOrders[0].takerFee.add(signedOrders[1].takerFee.dividedToIntegerBy(2));
expect(newBalances[makerAddress][signedOrders[0].makerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrders[0].makerTokenAddress].minus(makerTokenFillAmount),
balances[makerAddress][signedOrders[0].makerTokenAddress].minus(makerAmountSold),
);
expect(newBalances[makerAddress][signedOrders[0].takerTokenAddress]).to.be.bignumber.equal(
balances[makerAddress][signedOrders[0].takerTokenAddress].add(takerTokenFillAmount),
balances[makerAddress][signedOrders[0].takerTokenAddress].add(takerSellAmount),
);
expect(newBalances[makerAddress][zrx.address]).to.be.bignumber.equal(
balances[makerAddress][zrx.address].minus(makerFee),
);
expect(newBalances[takerAddress][signedOrders[0].takerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrders[0].takerTokenAddress].minus(takerTokenFillAmount),
balances[takerAddress][signedOrders[0].takerTokenAddress].minus(takerSellAmount),
);
expect(newBalances[takerAddress][signedOrders[0].makerTokenAddress]).to.be.bignumber.equal(
balances[takerAddress][signedOrders[0].makerTokenAddress].add(makerTokenFillAmount),
balances[takerAddress][signedOrders[0].makerTokenAddress].add(makerAmountSold),
);
expect(newBalances[takerAddress][zrx.address]).to.be.bignumber.equal(
balances[takerAddress][zrx.address].minus(takerFee),
@@ -673,33 +661,33 @@ describe('Exchange', () => {
);
});
it('should fill all signedOrders if cannot fill entire takerTokenFillAmount', async () => {
const takerTokenFillAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
it('should fill all signedOrders if cannot fill entire takerSellAmount', async () => {
const takerSellAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
_.forEach(signedOrders, signedOrder => {
balances[makerAddress][signedOrder.makerTokenAddress] = balances[makerAddress][
signedOrder.makerTokenAddress
].minus(signedOrder.makerTokenAmount);
].minus(signedOrder.makerSellAmount);
balances[makerAddress][signedOrder.takerTokenAddress] = balances[makerAddress][
signedOrder.takerTokenAddress
].add(signedOrder.takerTokenAmount);
].add(signedOrder.makerBuyAmount);
balances[makerAddress][zrx.address] = balances[makerAddress][zrx.address].minus(
signedOrder.makerFeeAmount,
signedOrder.makerFee,
);
balances[takerAddress][signedOrder.makerTokenAddress] = balances[takerAddress][
signedOrder.makerTokenAddress
].add(signedOrder.makerTokenAmount);
].add(signedOrder.makerSellAmount);
balances[takerAddress][signedOrder.takerTokenAddress] = balances[takerAddress][
signedOrder.takerTokenAddress
].minus(signedOrder.takerTokenAmount);
].minus(signedOrder.makerBuyAmount);
balances[takerAddress][zrx.address] = balances[takerAddress][zrx.address].minus(
signedOrder.takerFeeAmount,
signedOrder.takerFee,
);
balances[feeRecipientAddress][zrx.address] = balances[feeRecipientAddress][zrx.address].add(
signedOrder.makerFeeAmount.add(signedOrder.takerFeeAmount),
signedOrder.makerFee.add(signedOrder.takerFee),
);
});
await exWrapper.marketFillOrdersNoThrowAsync(signedOrders, takerAddress, {
takerTokenFillAmount,
await exWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerSellAmount,
});
const newBalances = await dmyBalances.getAsync();
@@ -714,8 +702,8 @@ describe('Exchange', () => {
];
return expect(
exWrapper.marketFillOrdersNoThrowAsync(signedOrders, takerAddress, {
takerTokenFillAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18),
exWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerSellAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18),
}),
).to.be.rejectedWith(constants.REVERT);
});
@@ -723,11 +711,11 @@ describe('Exchange', () => {
describe('batchCancelOrders', () => {
it('should be able to cancel multiple signedOrders', async () => {
const takerTokenCancelAmounts = _.map(signedOrders, signedOrder => signedOrder.takerTokenAmount);
const takerTokenCancelAmounts = _.map(signedOrders, signedOrder => signedOrder.makerBuyAmount);
await exWrapper.batchCancelOrdersAsync(signedOrders, makerAddress);
await exWrapper.batchFillOrdersAsync(signedOrders, takerAddress, {
takerTokenFillAmounts: takerTokenCancelAmounts,
takerSellAmounts: takerTokenCancelAmounts,
});
const newBalances = await dmyBalances.getAsync();
expect(balances).to.be.deep.equal(newBalances);