Changed the testing style to be more assertion based rather than reference based to leverage the fixtures from the integration tests
This commit is contained in:
parent
929bb86a54
commit
e9d49d96a6
@ -724,7 +724,7 @@ contract MixinMatchOrders is
|
||||
address takerAddress,
|
||||
LibFillResults.MatchedFillResults memory matchedFillResults
|
||||
)
|
||||
private
|
||||
internal
|
||||
{
|
||||
address leftFeeRecipientAddress = leftOrder.feeRecipientAddress;
|
||||
address rightFeeRecipientAddress = rightOrder.feeRecipientAddress;
|
||||
|
@ -39,6 +39,16 @@ contract TestExchangeInternals is
|
||||
Exchange(chainId)
|
||||
{}
|
||||
|
||||
function assertValidMatch(
|
||||
LibOrder.Order memory leftOrder,
|
||||
LibOrder.Order memory rightOrder
|
||||
)
|
||||
public
|
||||
view
|
||||
{
|
||||
_assertValidMatch(leftOrder, rightOrder);
|
||||
}
|
||||
|
||||
function calculateFillResults(
|
||||
Order memory order,
|
||||
uint256 takerAssetFilledAmount
|
||||
@ -50,6 +60,43 @@ contract TestExchangeInternals is
|
||||
return _calculateFillResults(order, takerAssetFilledAmount);
|
||||
}
|
||||
|
||||
function calculateCompleteFillBoth(
|
||||
uint256 leftMakerAssetAmountRemaining,
|
||||
uint256 leftTakerAssetAmountRemaining,
|
||||
uint256 rightMakerAssetAmountRemaining,
|
||||
uint256 rightTakerAssetAmountRemaining
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (MatchedFillResults memory fillResults)
|
||||
{
|
||||
_calculateCompleteFillBoth(
|
||||
fillResults,
|
||||
leftMakerAssetAmountRemaining,
|
||||
leftTakerAssetAmountRemaining,
|
||||
rightMakerAssetAmountRemaining,
|
||||
rightTakerAssetAmountRemaining
|
||||
);
|
||||
return fillResults;
|
||||
}
|
||||
|
||||
function calculateCompleteRightFill(
|
||||
LibOrder.Order memory leftOrder,
|
||||
uint256 rightMakerAssetAmountRemaining,
|
||||
uint256 rightTakerAssetAmountRemaining
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (MatchedFillResults memory fillResults)
|
||||
{
|
||||
_calculateCompleteRightFill(
|
||||
fillResults,
|
||||
leftOrder,
|
||||
rightMakerAssetAmountRemaining,
|
||||
rightTakerAssetAmountRemaining
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Call `_updateFilledState()` but first set `filled[order]` to
|
||||
/// `orderTakerAssetFilledAmount`.
|
||||
function testUpdateFilledState(
|
||||
@ -82,6 +129,26 @@ contract TestExchangeInternals is
|
||||
_settleOrder(orderHash, order, takerAddress, fillResults);
|
||||
}
|
||||
|
||||
function settleMatchOrders(
|
||||
bytes32 leftOrderHash,
|
||||
bytes32 rightOrderHash,
|
||||
LibOrder.Order memory leftOrder,
|
||||
LibOrder.Order memory rightOrder,
|
||||
address takerAddress,
|
||||
LibFillResults.MatchedFillResults memory matchedFillResults
|
||||
)
|
||||
public
|
||||
{
|
||||
_settleMatchedOrders(
|
||||
leftOrderHash,
|
||||
rightOrderHash,
|
||||
leftOrder,
|
||||
rightOrder,
|
||||
takerAddress,
|
||||
matchedFillResults
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Overidden to only log arguments so we can test `_settleOrder()`.
|
||||
function _dispatchTransferFrom(
|
||||
bytes32 orderHash,
|
||||
|
@ -1,11 +1,23 @@
|
||||
import { ReferenceFunctions as ExchangeLibsReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import { constants } from '@0x/contracts-test-utils';
|
||||
import { ReferenceFunctions as UtilsReferenceFunctions } from '@0x/contracts-utils';
|
||||
import { FillResults, MatchedFillResults, OrderWithoutDomain } from '@0x/types';
|
||||
import { ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
|
||||
import { FillResults, MatchedFillResults, Order, OrderWithoutDomain } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
const { safeGetPartialAmountCeil, safeGetPartialAmountFloor } = ExchangeLibsReferenceFunctions;
|
||||
const { safeSub } = UtilsReferenceFunctions;
|
||||
const { safeMul, safeSub } = UtilsReferenceFunctions;
|
||||
|
||||
/**
|
||||
* Ensure that there is a profitable spread.
|
||||
*/
|
||||
export function assertValidMatch(leftOrder: Order, rightOrder: Order): void {
|
||||
if (safeMul(leftOrder.makerAssetAmount, rightOrder.makerAssetAmount) < safeMul(leftOrder.takerAssetAmount, rightOrder.takerAssetAmount)) {
|
||||
const orderHashHexLeft = orderHashUtils.getOrderHashHex(leftOrder);
|
||||
const orderHashHexRight = orderHashUtils.getOrderHashHex(rightOrder);
|
||||
throw new ExchangeRevertErrors.NegativeSpreadError(orderHashHexLeft, orderHashHexRight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates amounts filled and fees paid by maker and taker.
|
||||
@ -51,14 +63,8 @@ export function calculateMatchedFillResults(
|
||||
rightOrderTakerAssetFilledAmount,
|
||||
);
|
||||
|
||||
// Calculate the profit from the matching
|
||||
matchedFillResults.profitInLeftMakerAsset = safeSub(
|
||||
matchedFillResults.left.makerAssetFilledAmount,
|
||||
matchedFillResults.right.takerAssetFilledAmount,
|
||||
);
|
||||
|
||||
if (leftTakerAssetAmountRemaining.isGreaterThan(rightMakerAssetAmountRemaining)) {
|
||||
// Case 1: Right order is fully filled
|
||||
// Case 1
|
||||
calculateCompleteRightFill(
|
||||
leftOrder,
|
||||
rightMakerAssetAmountRemaining,
|
||||
@ -66,7 +72,7 @@ export function calculateMatchedFillResults(
|
||||
matchedFillResults,
|
||||
);
|
||||
} else if (leftTakerAssetAmountRemaining.isLessThan(rightMakerAssetAmountRemaining)) {
|
||||
// Case 2: Left order is fully filled
|
||||
// Case 2
|
||||
matchedFillResults.left.makerAssetFilledAmount = leftMakerAssetAmountRemaining;
|
||||
matchedFillResults.left.takerAssetFilledAmount = leftTakerAssetAmountRemaining;
|
||||
matchedFillResults.right.makerAssetFilledAmount = leftTakerAssetAmountRemaining;
|
||||
@ -76,8 +82,7 @@ export function calculateMatchedFillResults(
|
||||
leftTakerAssetAmountRemaining,
|
||||
);
|
||||
} else {
|
||||
// Case 3: Both orders are fully filled. Technically, this could be captured by the above cases, but
|
||||
// this calculation will be more precise since it does not include rounding.
|
||||
// Case 3
|
||||
calculateCompleteFillBoth(
|
||||
leftMakerAssetAmountRemaining,
|
||||
leftTakerAssetAmountRemaining,
|
||||
@ -94,6 +99,12 @@ export function calculateMatchedFillResults(
|
||||
matchedFillResults,
|
||||
);
|
||||
|
||||
// Calculate the profit from the matching
|
||||
matchedFillResults.profitInLeftMakerAsset = safeSub(
|
||||
matchedFillResults.left.makerAssetFilledAmount,
|
||||
matchedFillResults.right.takerAssetFilledAmount,
|
||||
);
|
||||
|
||||
return matchedFillResults;
|
||||
}
|
||||
|
||||
@ -206,18 +217,20 @@ function getRemainingFillAmounts(
|
||||
leftOrderTakerAssetFilledAmount: BigNumber,
|
||||
rightOrderTakerAssetFilledAmount: BigNumber,
|
||||
): [ BigNumber, BigNumber, BigNumber, BigNumber ] {
|
||||
const leftTakerAssetRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount);
|
||||
const rightTakerAssetRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount);
|
||||
return [
|
||||
safeGetPartialAmountFloor(
|
||||
leftOrder.makerAssetAmount,
|
||||
leftOrder.takerAssetAmount,
|
||||
leftOrderTakerAssetFilledAmount
|
||||
leftTakerAssetRemaining,
|
||||
),
|
||||
safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount),
|
||||
leftTakerAssetRemaining,
|
||||
safeGetPartialAmountFloor(
|
||||
rightOrder.makerAssetAmount,
|
||||
rightOrder.takerAssetAmount,
|
||||
rightOrderTakerAssetFilledAmount
|
||||
rightTakerAssetRemaining,
|
||||
),
|
||||
safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount),
|
||||
rightTakerAssetRemaining,
|
||||
];
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ describe('AssetProxyDispatcher', () => {
|
||||
return expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should should revert with the correct error when assetData length < 4 bytes', async () => {
|
||||
it('should revert with the correct error when assetData length < 4 bytes', async () => {
|
||||
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
|
||||
from: owner,
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,480 +0,0 @@
|
||||
import {
|
||||
artifacts as assetProxyArtifacts,
|
||||
ERC1155ProxyContract,
|
||||
ERC1155ProxyWrapper,
|
||||
ERC20ProxyContract,
|
||||
ERC20Wrapper,
|
||||
ERC721ProxyContract,
|
||||
ERC721Wrapper,
|
||||
MultiAssetProxyContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { ERC1155Contract as ERC1155TokenContract, Erc1155Wrapper as ERC1155Wrapper } from '@0x/contracts-erc1155';
|
||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { ReferenceFunctions as ExchangeLibsReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import {
|
||||
blockchainTests,
|
||||
chaiSetup,
|
||||
constants,
|
||||
describe,
|
||||
OrderFactory,
|
||||
orderUtils,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
|
||||
import { OrderWithoutDomain, OrderStatus, SignedOrder } from '@0x/types';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
artifacts,
|
||||
constants as exchangeConstants,
|
||||
ExchangeContract,
|
||||
ExchangeWrapper,
|
||||
ReentrantERC20TokenContract,
|
||||
ReferenceFunctions,
|
||||
TestMatchOrdersContract,
|
||||
} from '../src';
|
||||
import { calculateCompleteFillBoth, calculateCompleteRightFill } from '../src/reference_functions';
|
||||
|
||||
import { MatchOrderTester, TokenBalances } from './utils/match_order_tester';
|
||||
|
||||
// Reduce the number of tokens to deploy to speed up tests, since we don't need
|
||||
// so many.
|
||||
constants.NUM_DUMMY_ERC721_TO_DEPLOY = 1;
|
||||
constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY = 1;
|
||||
|
||||
/**
|
||||
* Tests the _calculateCompleteFillBoth function with the provided inputs by making a call
|
||||
* to the provided matchOrders contract's externalCalculateCompleteFillBoth function with the
|
||||
* provided inputs and asserting that the resultant struct is correct.
|
||||
* @param matchOrders The TestMatchOrders contract object that should be used to make the call to
|
||||
* the smart contract.
|
||||
* @param leftMakerAssetAmountRemaining The left maker asset remaining field for the function call.
|
||||
* @param leftTakerAssetAmountRemaining The left taker asset remaining field for the function call.
|
||||
* @param rightMakerAssetAmountRemaining The right maker asset remaining field for the function call.
|
||||
* @param rightTakerAssetAmountRemaining The right taker asset remaining field for the function call.
|
||||
*/
|
||||
async function testCalculateCompleteFillBothAsync(
|
||||
matchOrders: TestMatchOrdersContract,
|
||||
args: BigNumber[],
|
||||
): Promise<void> {
|
||||
// Ensure that the correct number of arguments were provided.
|
||||
expect(args.length).to.be.eq(4);
|
||||
|
||||
// Get the expected matched fill results from calling the reference function.
|
||||
const expectedMatchedFillResults = calculateCompleteFillBoth(
|
||||
args[0],
|
||||
args[1],
|
||||
args[2],
|
||||
args[3],
|
||||
);
|
||||
|
||||
// Get the resultant matched fill results from the call to _calculateCompleteFillBoth.
|
||||
const actualMatchedFillResults = await matchOrders.externalCalculateCompleteFillBoth.callAsync(
|
||||
args[0],
|
||||
args[1],
|
||||
args[2],
|
||||
args[3],
|
||||
);
|
||||
|
||||
expect(actualMatchedFillResults).to.be.deep.eq(expectedMatchedFillResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the _calculateCompleteRightFill function with the provided inputs by making a call
|
||||
* to the provided matchOrders contract's externalCalculateCompleteRightFill function with the
|
||||
* provided inputs and asserting that the resultant struct is correct.
|
||||
* @param matchOrders The TestMatchOrders contract object that should be used to make the call to
|
||||
* the smart contract.
|
||||
*/
|
||||
async function testCalculateCompleteRightFillAsync(
|
||||
matchOrders: TestMatchOrdersContract,
|
||||
leftOrder: OrderWithoutDomain,
|
||||
args: BigNumber[],
|
||||
): Promise<void> {
|
||||
// Ensure that the correct number of arguments were provided.
|
||||
expect(args.length).to.be.eq(2);
|
||||
|
||||
// Get the expected matched fill results from calling the reference function.
|
||||
const expectedMatchedFillResults = calculateCompleteRightFill(
|
||||
leftOrder,
|
||||
args[0],
|
||||
args[1],
|
||||
);
|
||||
|
||||
// Get the resultant matched fill results from the call to _calculateCompleteRightFill.
|
||||
const actualMatchedFillResults = await matchOrders.publicCalculateCompleteRightFill.callAsync(
|
||||
leftOrder,
|
||||
args[0],
|
||||
args[1],
|
||||
);
|
||||
|
||||
expect(actualMatchedFillResults).to.be.deep.eq(expectedMatchedFillResults);
|
||||
}
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
blockchainTests.resets.only('MatchOrders Tests', ({ web3Wrapper, txDefaults }) => {
|
||||
let chainId: number;
|
||||
let makerAddressLeft: string;
|
||||
let makerAddressRight: string;
|
||||
let owner: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipientAddressLeft: string;
|
||||
let feeRecipientAddressRight: string;
|
||||
|
||||
let erc20Tokens: DummyERC20TokenContract[];
|
||||
let erc721Token: DummyERC721TokenContract;
|
||||
let erc1155Token: ERC1155TokenContract;
|
||||
let reentrantErc20Token: ReentrantERC20TokenContract;
|
||||
let exchange: ExchangeContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let erc721Proxy: ERC721ProxyContract;
|
||||
let erc1155Proxy: ERC1155ProxyContract;
|
||||
let erc1155ProxyWrapper: ERC1155ProxyWrapper;
|
||||
|
||||
let exchangeWrapper: ExchangeWrapper;
|
||||
let erc20Wrapper: ERC20Wrapper;
|
||||
let erc721Wrapper: ERC721Wrapper;
|
||||
let erc1155Wrapper: ERC1155Wrapper;
|
||||
let orderFactoryLeft: OrderFactory;
|
||||
let orderFactoryRight: OrderFactory;
|
||||
|
||||
let tokenBalances: TokenBalances;
|
||||
|
||||
let defaultERC20MakerAssetAddress: string;
|
||||
let defaultERC20TakerAssetAddress: string;
|
||||
let defaultERC721AssetAddress: string;
|
||||
let defaultERC1155AssetAddress: string;
|
||||
let defaultFeeTokenAddress: string;
|
||||
|
||||
let matchOrders: TestMatchOrdersContract;
|
||||
|
||||
before(async () => {
|
||||
// Get the chain ID.
|
||||
chainId = await providerUtils.getChainIdAsync(provider);
|
||||
// Create accounts
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const usedAddresses = ([
|
||||
owner,
|
||||
makerAddressLeft,
|
||||
makerAddressRight,
|
||||
takerAddress,
|
||||
feeRecipientAddressLeft,
|
||||
feeRecipientAddressRight,
|
||||
] = accounts);
|
||||
const addressesWithBalances = usedAddresses.slice(1);
|
||||
// Create wrappers
|
||||
erc20Wrapper = new ERC20Wrapper(provider, addressesWithBalances, owner);
|
||||
erc721Wrapper = new ERC721Wrapper(provider, addressesWithBalances, owner);
|
||||
erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, addressesWithBalances, owner);
|
||||
// Deploy ERC20 token & ERC20 proxy
|
||||
const numDummyErc20ToDeploy = 4;
|
||||
erc20Tokens = await erc20Wrapper.deployDummyTokensAsync(numDummyErc20ToDeploy, constants.DUMMY_TOKEN_DECIMALS);
|
||||
erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
// Deploy ERC721 token and proxy
|
||||
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
||||
erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
// Deploy ERC1155 token and proxy
|
||||
[erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync();
|
||||
erc1155Token = erc1155Wrapper.getContract();
|
||||
erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync();
|
||||
await erc1155ProxyWrapper.setBalancesAndAllowancesAsync();
|
||||
// Deploy MultiAssetProxy.
|
||||
const multiAssetProxyContract = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
assetProxyArtifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
// Depoy exchange
|
||||
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
new BigNumber(chainId),
|
||||
);
|
||||
exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxyContract.address, owner);
|
||||
// Authorize proxies.
|
||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchange.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchange.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchange.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await multiAssetProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchange.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxyContract.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxyContract.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxyContract.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc20Proxy.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc721Proxy.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc1155Proxy.address,
|
||||
{ from: owner },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
reentrantErc20Token = await ReentrantERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ReentrantERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
exchange.address,
|
||||
);
|
||||
|
||||
// Set default addresses
|
||||
defaultERC20MakerAssetAddress = erc20Tokens[0].address;
|
||||
defaultERC20TakerAssetAddress = erc20Tokens[1].address;
|
||||
defaultFeeTokenAddress = erc20Tokens[2].address;
|
||||
defaultERC721AssetAddress = erc721Token.address;
|
||||
defaultERC1155AssetAddress = erc1155Token.address;
|
||||
const domain = {
|
||||
verifyingContractAddress: exchange.address,
|
||||
chainId,
|
||||
};
|
||||
// Create default order parameters
|
||||
const defaultOrderParamsLeft = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
makerAddress: makerAddressLeft,
|
||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
|
||||
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
||||
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
||||
feeRecipientAddress: feeRecipientAddressLeft,
|
||||
domain,
|
||||
};
|
||||
const defaultOrderParamsRight = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
makerAddress: makerAddressRight,
|
||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
|
||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
||||
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
||||
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress),
|
||||
feeRecipientAddress: feeRecipientAddressRight,
|
||||
domain,
|
||||
};
|
||||
const privateKeyLeft = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressLeft)];
|
||||
orderFactoryLeft = new OrderFactory(privateKeyLeft, defaultOrderParamsLeft);
|
||||
const privateKeyRight = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressRight)];
|
||||
orderFactoryRight = new OrderFactory(privateKeyRight, defaultOrderParamsRight);
|
||||
|
||||
// Deploy the TestMatchOrders contract
|
||||
matchOrders = await TestMatchOrdersContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMatchOrders,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
});
|
||||
|
||||
describe('_assertValidMatch', () => {
|
||||
it('should revert if the prices of the left order is less than the price of the right order', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
});
|
||||
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(50, 18),
|
||||
});
|
||||
const orderHashHexLeft = orderHashUtils.getOrderHashHex(signedOrderLeft);
|
||||
const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight);
|
||||
const expectedError = new ExchangeRevertErrors.NegativeSpreadError(orderHashHexLeft, orderHashHexRight);
|
||||
const tx = matchOrders.publicAssertValidMatch.callAsync(signedOrderLeft, signedOrderRight);
|
||||
expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should revert if the prices of the left and right orders are equal', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
});
|
||||
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(50, 18),
|
||||
});
|
||||
const orderHashHexLeft = orderHashUtils.getOrderHashHex(signedOrderLeft);
|
||||
const orderHashHexRight = orderHashUtils.getOrderHashHex(signedOrderRight);
|
||||
const expectedError = new ExchangeRevertErrors.NegativeSpreadError(orderHashHexLeft, orderHashHexRight);
|
||||
const tx = matchOrders.publicAssertValidMatch.callAsync(signedOrderLeft, signedOrderRight);
|
||||
expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should succeed if the price of the left order is higher than the price of the right', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(50, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
});
|
||||
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 18),
|
||||
});
|
||||
await matchOrders.publicAssertValidMatch.callAsync(signedOrderLeft, signedOrderRight)
|
||||
});
|
||||
});
|
||||
|
||||
describe('_calculateMatchedFillResults', () => {
|
||||
// FIXME - Test case 2 and verify that it is correctly hitting case 1 and 3.
|
||||
// FIXME - Test the profit calculations for all three cases
|
||||
});
|
||||
|
||||
describe('_calculateCompleteFillBoth', () => {
|
||||
it('should assign everything to zero if all inputs are zero', async () => {
|
||||
await testCalculateCompleteFillBothAsync(
|
||||
matchOrders,
|
||||
[0, 0, 0, 0].map(value => new BigNumber(value)),
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly update the fillResults with nonzero input', async () => {
|
||||
await testCalculateCompleteFillBothAsync(
|
||||
matchOrders,
|
||||
[17, 98, 75, 13].map(value => new BigNumber(value)),
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly update the fillResults with nonzero input', async () => {
|
||||
await testCalculateCompleteFillBothAsync(
|
||||
matchOrders,
|
||||
[
|
||||
5,
|
||||
10,
|
||||
10,
|
||||
5,
|
||||
].map(value => new BigNumber(value)),
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly update the fillResults with nonzero input', async () => {
|
||||
await testCalculateCompleteFillBothAsync(
|
||||
matchOrders,
|
||||
[
|
||||
Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(10, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(10, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||
].map(value => new BigNumber(value)),
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly update the fillResults with nonzero input', async () => {
|
||||
await testCalculateCompleteFillBothAsync(
|
||||
matchOrders,
|
||||
[
|
||||
Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(10, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(10, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(2, 18),
|
||||
].map(value => new BigNumber(value)),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_calculateCompleteRightFill', () => {
|
||||
/**
|
||||
* NOTE(jalextowle): These test cases actually cover all code branches of _calculateCompleteRightFill (in
|
||||
* fact any one of these test cases provide 100% coverage), but they do not verify that _safeGetPartialAmountCeil
|
||||
* and _safeGetPartialAmountFloor revert appropriately. Keeping in the spirit of unit testing, these functions
|
||||
* are unit tested to ensure that they exhibit the correct behavior in a more isolated setting.
|
||||
*/
|
||||
|
||||
it('should correctly calculate the complete right fill', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAddress: makerAddressLeft,
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(17, 0),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(98, 0),
|
||||
feeRecipientAddress: feeRecipientAddressLeft,
|
||||
});
|
||||
await testCalculateCompleteRightFillAsync(
|
||||
matchOrders,
|
||||
signedOrderLeft,
|
||||
[
|
||||
Web3Wrapper.toBaseUnitAmount(75, 0),
|
||||
Web3Wrapper.toBaseUnitAmount(13, 0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly calculate the complete right fill', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAddress: makerAddressLeft,
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(12, 0),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(97, 0),
|
||||
feeRecipientAddress: feeRecipientAddressLeft,
|
||||
});
|
||||
await testCalculateCompleteRightFillAsync(
|
||||
matchOrders,
|
||||
signedOrderLeft,
|
||||
[
|
||||
Web3Wrapper.toBaseUnitAmount(89, 0),
|
||||
Web3Wrapper.toBaseUnitAmount(1, 0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly calculate the complete right fill', async () => {
|
||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||
makerAddress: makerAddressLeft,
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(50, 18),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(100, 18),
|
||||
feeRecipientAddress: feeRecipientAddressLeft,
|
||||
});
|
||||
await testCalculateCompleteRightFillAsync(
|
||||
matchOrders,
|
||||
signedOrderLeft,
|
||||
[
|
||||
Web3Wrapper.toBaseUnitAmount(10, 18),
|
||||
Web3Wrapper.toBaseUnitAmount(2, 18),
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_settleMatchedOrders', () => {
|
||||
// FIXME -
|
||||
});
|
||||
});
|
||||
// tslint:disable-line:max-file-line-count
|
Loading…
x
Reference in New Issue
Block a user