aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test/exchange
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts/test/exchange')
-rw-r--r--packages/contracts/test/exchange/combinatorial_tests.ts48
-rw-r--r--packages/contracts/test/exchange/core.ts547
-rw-r--r--packages/contracts/test/exchange/dispatcher.ts21
-rw-r--r--packages/contracts/test/exchange/fill_order.ts285
-rw-r--r--packages/contracts/test/exchange/match_orders.ts28
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts10
-rw-r--r--packages/contracts/test/exchange/transactions.ts43
-rw-r--r--packages/contracts/test/exchange/wrapper.ts34
8 files changed, 460 insertions, 556 deletions
diff --git a/packages/contracts/test/exchange/combinatorial_tests.ts b/packages/contracts/test/exchange/combinatorial_tests.ts
new file mode 100644
index 000000000..f5f795bbe
--- /dev/null
+++ b/packages/contracts/test/exchange/combinatorial_tests.ts
@@ -0,0 +1,48 @@
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import * as _ from 'lodash';
+
+import { chaiSetup } from '../../src/utils/chai_setup';
+import { CoreCombinatorialUtils, coreCombinatorialUtilsFactoryAsync } from '../../src/utils/core_combinatorial_utils';
+import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
+
+import { FillScenario } from '../../src/utils/types';
+
+chaiSetup.configure();
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('Combinatorial tests', () => {
+ let coreCombinatorialUtils: CoreCombinatorialUtils;
+
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ coreCombinatorialUtils = await coreCombinatorialUtilsFactoryAsync(web3Wrapper, txDefaults);
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ const test = (fillScenarios: FillScenario[]) => {
+ _.forEach(fillScenarios, fillScenario => {
+ const orderScenario = fillScenario.orderScenario;
+ const description = `Combinatorial OrderFill: ${orderScenario.feeRecipientScenario} ${
+ orderScenario.makerAssetAmountScenario
+ } ${orderScenario.takerAssetAmountScenario} ${orderScenario.makerFeeScenario} ${
+ orderScenario.takerFeeScenario
+ } ${orderScenario.expirationTimeSecondsScenario} ${orderScenario.makerAssetDataScenario} ${
+ orderScenario.takerAssetDataScenario
+ }`;
+ it(description, async () => {
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ });
+ };
+
+ const allFillScenarios = CoreCombinatorialUtils.generateFillOrderCombinations();
+
+ describe('Fills orders', () => test(allFillScenarios));
+});
diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts
index 5b2d4590f..52bddf996 100644
--- a/packages/contracts/test/exchange/core.ts
+++ b/packages/contracts/test/exchange/core.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
-import { AssetProxyId, SignedOrder } from '@0xproject/types';
+import { AssetProxyId, RevertReasons, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -11,13 +11,12 @@ import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/d
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
-import {
- CancelContractEventArgs,
- ExchangeContract,
- FillContractEventArgs,
-} from '../../src/generated_contract_wrappers/exchange';
+import { CancelContractEventArgs, ExchangeContract } from '../../src/generated_contract_wrappers/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
+import {
+ expectRevertOrAlwaysFailingTransactionAsync,
+ expectRevertReasonOrAlwaysFailingTransactionAsync,
+} from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -71,7 +70,10 @@ describe('Exchange core', () => {
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync();
+ [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ constants.NUM_DUMMY_ERC20_TO_DEPLOY,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
@@ -130,295 +132,6 @@ describe('Exchange core', () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
});
- it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => {
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- });
-
- const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
-
- const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
-
- const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
-
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const makerAssetFilledAmount = takerAssetFillAmount
- .times(signedOrder.makerAssetAmount)
- .dividedToIntegerBy(signedOrder.takerAssetAmount);
- const makerFeePaid = signedOrder.makerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- const takerFeePaid = signedOrder.takerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount),
- );
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(makerAssetFilledAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
- );
- });
-
- it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => {
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- });
-
- const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
-
- const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
-
- const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
-
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const makerAssetFilledAmount = takerAssetFillAmount
- .times(signedOrder.makerAssetAmount)
- .dividedToIntegerBy(signedOrder.takerAssetAmount);
- const makerFeePaid = signedOrder.makerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- const takerFeePaid = signedOrder.takerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount),
- );
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(makerAssetFilledAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
- );
- });
-
- it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => {
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
- });
-
- const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
-
- const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
-
- const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
-
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const makerAssetFilledAmount = takerAssetFillAmount
- .times(signedOrder.makerAssetAmount)
- .dividedToIntegerBy(signedOrder.takerAssetAmount);
- const makerFeePaid = signedOrder.makerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- const takerFeePaid = signedOrder.takerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount),
- );
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(makerAssetFilledAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
- );
- });
-
- it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
- signedOrder = orderFactory.newSignedOrder({
- takerAddress,
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
- });
-
- const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
-
- const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
-
- const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
- orderHashUtils.getOrderHashHex(signedOrder),
- );
- const expectedMakerAmountBoughtAfter = takerAssetFillAmount.add(takerAssetFilledAmountBefore);
- expect(makerAmountBoughtAfter).to.be.bignumber.equal(expectedMakerAmountBoughtAfter);
-
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const makerAssetFilledAmount = takerAssetFillAmount
- .times(signedOrder.makerAssetAmount)
- .dividedToIntegerBy(signedOrder.takerAssetAmount);
- const makerFeePaid = signedOrder.makerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- const takerFeePaid = signedOrder.takerFee
- .times(makerAssetFilledAmount)
- .dividedToIntegerBy(signedOrder.makerAssetAmount);
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount),
- );
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(makerAssetFilledAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
- );
- });
-
- it('should fill remaining value if takerAssetFillAmount > remaining takerAssetAmount', async () => {
- const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
-
- const res = await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
- takerAssetFillAmount: signedOrder.takerAssetAmount,
- });
- const log = res.logs[0] as LogWithDecodedArgs<FillContractEventArgs>;
- expect(log.args.takerAssetFilledAmount).to.be.bignumber.equal(
- signedOrder.takerAssetAmount.minus(takerAssetFillAmount),
- );
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(signedOrder.makerAssetAmount),
- );
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(signedOrder.takerAssetAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(signedOrder.makerFee),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(signedOrder.takerAssetAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(signedOrder.makerAssetAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(signedOrder.takerFee),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.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 exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
- takerAssetFillAmount: signedOrder.takerAssetAmount.div(divisor),
- });
- expect(res.logs).to.have.length(1);
-
- const log = res.logs[0] as LogWithDecodedArgs<FillContractEventArgs>;
- const logArgs = log.args;
- const expectedFilledMakerAssetAmount = signedOrder.makerAssetAmount.div(divisor);
- const expectedFilledTakerAssetAmount = signedOrder.takerAssetAmount.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(takerAddress).to.be.equal(logArgs.senderAddress);
- expect(signedOrder.feeRecipientAddress).to.be.equal(logArgs.feeRecipientAddress);
- expect(signedOrder.makerAssetData).to.be.equal(logArgs.makerAssetData);
- expect(signedOrder.takerAssetData).to.be.equal(logArgs.takerAssetData);
- expect(expectedFilledMakerAssetAmount).to.be.bignumber.equal(logArgs.makerAssetFilledAmount);
- expect(expectedFilledTakerAssetAmount).to.be.bignumber.equal(logArgs.takerAssetFilledAmount);
- expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeePaid);
- expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeePaid);
- expect(orderHashUtils.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,
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
- });
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
it('should throw if signature is invalid', async () => {
signedOrder = orderFactory.newSignedOrder({
@@ -432,98 +145,18 @@ describe('Exchange core', () => {
const invalidSigBuff = Buffer.concat([v, invalidR, invalidS, signatureType]);
const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
signedOrder.signature = invalidSigHex;
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if makerAssetAmount is 0', async () => {
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: new BigNumber(0),
- });
-
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if takerAssetAmount is 0', async () => {
- signedOrder = orderFactory.newSignedOrder({
- takerAssetAmount: new BigNumber(0),
- });
-
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if takerAssetFillAmount is 0', async () => {
- signedOrder = orderFactory.newSignedOrder();
-
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
- takerAssetFillAmount: new BigNumber(0),
- }),
- );
- });
-
- it('should throw if maker erc20Balances are too low to fill order', async () => {
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
- });
-
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if taker erc20Balances are too low to fill order', async () => {
- signedOrder = orderFactory.newSignedOrder({
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
- });
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if maker allowances are too low to fill order', async () => {
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if taker allowances are too low to fill order', async () => {
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
- );
- });
-
- it('should throw if an order is expired', async () => {
- signedOrder = orderFactory.newSignedOrder({
- expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
- });
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
+ RevertReasons.InvalidOrderSignature,
);
});
it('should throw if no value is filled', async () => {
signedOrder = orderFactory.newSignedOrder();
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
+ RevertReasons.OrderUnfillable,
);
});
});
@@ -535,8 +168,9 @@ describe('Exchange core', () => {
});
it('should throw if not sent by maker', async () => {
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress),
+ RevertReasons.InvalidMaker,
);
});
@@ -545,8 +179,9 @@ describe('Exchange core', () => {
makerAssetAmount: new BigNumber(0),
});
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -555,17 +190,19 @@ describe('Exchange core', () => {
takerAssetAmount: new BigNumber(0),
});
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
+ RevertReasons.OrderUnfillable,
);
});
it('should be able to cancel a full order', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: signedOrder.takerAssetAmount.div(2),
}),
+ RevertReasons.OrderUnfillable,
);
});
@@ -586,8 +223,9 @@ describe('Exchange core', () => {
it('should throw if already cancelled', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -595,8 +233,9 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
});
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -612,10 +251,11 @@ describe('Exchange core', () => {
});
const fillTakerAssetAmount2 = new BigNumber(1);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: fillTakerAssetAmount2,
}),
+ RevertReasons.RoundingError,
);
});
});
@@ -625,16 +265,18 @@ describe('Exchange core', () => {
const orderEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
const lesserOrderEpoch = new BigNumber(0);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrdersUpToAsync(lesserOrderEpoch, makerAddress),
+ RevertReasons.InvalidNewOrderEpoch,
);
});
it('should fail to set orderEpoch equal to existing orderEpoch', async () => {
const orderEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress),
+ RevertReasons.InvalidNewOrderEpoch,
);
});
@@ -705,32 +347,6 @@ describe('Exchange core', () => {
});
describe('Testing Exchange of ERC721 Tokens', () => {
- it('should successfully exchange a single token between the maker and taker (via fillOrder)', async () => {
- // Construct Exchange parameters
- const makerAssetId = erc721MakerAssetIds[0];
- const takerAssetId = erc721TakerAssetIds[1];
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
- });
- // Verify pre-conditions
- const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(initialOwnerMakerAsset).to.be.bignumber.equal(makerAddress);
- const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
- expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- // Call Exchange
- const takerAssetFillAmount = signedOrder.takerAssetAmount;
- // tslint:disable-next-line:no-unused-variable
- const res = await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
- // Verify post-conditions
- const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(makerAddress);
- });
-
it('should throw when maker does not own the token with id makerAssetId', async () => {
// Construct Exchange parameters
const makerAssetId = erc721TakerAssetIds[0];
@@ -792,8 +408,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount;
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
+ RevertReasons.InvalidAmount,
);
});
@@ -814,110 +431,26 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount;
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
+ RevertReasons.InvalidAmount,
);
});
it('should throw on partial fill', async () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
- const takerAssetId = erc721TakerAssetIds[0];
- signedOrder = orderFactory.newSignedOrder({
- makerAssetAmount: new BigNumber(1),
- takerAssetAmount: new BigNumber(0),
- makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
- });
- // Verify pre-conditions
- const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(initialOwnerMakerAsset).to.be.bignumber.equal(makerAddress);
- const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
- expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
- // Call Exchange
- const takerAssetFillAmount = signedOrder.takerAssetAmount;
- return expectRevertOrAlwaysFailingTransactionAsync(
- exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
- );
- });
-
- it('should successfully fill order when makerAsset is ERC721 and takerAsset is ERC20', async () => {
- // Construct Exchange parameters
- const makerAssetId = erc721MakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
});
- // Verify pre-conditions
- const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(initialOwnerMakerAsset).to.be.bignumber.equal(makerAddress);
- // Call Exchange
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- const takerAssetFillAmount = signedOrder.takerAssetAmount;
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
- // Verify ERC721 token was transferred from Maker to Taker
- const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
- // Verify ERC20 tokens were transferred from Taker to Maker & fees were paid correctly
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[makerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(signedOrder.makerFee),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(signedOrder.takerFee),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(
- signedOrder.makerFee.add(signedOrder.takerFee),
- ),
- );
- });
-
- it('should successfully fill order when makerAsset is ERC20 and takerAsset is ERC721', async () => {
- // Construct Exchange parameters
- const takerAssetId = erc721TakerAssetIds[0];
- signedOrder = orderFactory.newSignedOrder({
- takerAssetAmount: new BigNumber(1),
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
- makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- });
- // Verify pre-conditions
- const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
- expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- const takerAssetFillAmount = signedOrder.takerAssetAmount;
- await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
- // Verify ERC721 token was transferred from Taker to Maker
- const newOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
- expect(newOwnerTakerAsset).to.be.bignumber.equal(makerAddress);
- // Verify ERC20 tokens were transferred from Maker to Taker & fees were paid correctly
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].add(signedOrder.makerAssetAmount),
- );
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(signedOrder.makerAssetAmount),
- );
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(signedOrder.makerFee),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].minus(signedOrder.takerFee),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].add(
- signedOrder.makerFee.add(signedOrder.takerFee),
- ),
+ const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
+ exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
+ RevertReasons.RoundingError,
);
});
});
diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts
index f96f15f16..41ea88d4e 100644
--- a/packages/contracts/test/exchange/dispatcher.ts
+++ b/packages/contracts/test/exchange/dispatcher.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
-import { AssetProxyId } from '@0xproject/types';
+import { AssetProxyId, RevertReasons } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -9,7 +9,7 @@ import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c2
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
import { TestAssetProxyDispatcherContract } from '../../src/generated_contract_wrappers/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/utils/artifacts';
-import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
+import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -48,7 +48,10 @@ describe('AssetProxyDispatcher', () => {
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- [zrxToken] = await erc20Wrapper.deployDummyTokensAsync();
+ [zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ constants.NUM_DUMMY_ERC20_TO_DEPLOY,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
@@ -175,13 +178,14 @@ describe('AssetProxyDispatcher', () => {
const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
expect(proxyAddress).to.be.equal(erc20Proxy.address);
// The following transaction will throw because the currentAddress is no longer constants.NULL_ADDRESS
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC20,
erc20Proxy.address,
constants.NULL_ADDRESS,
{ from: owner },
),
+ RevertReasons.AssetProxyMismatch,
);
});
@@ -216,25 +220,27 @@ describe('AssetProxyDispatcher', () => {
it('should throw if requesting address is not owner', async () => {
const prevProxyAddress = constants.NULL_ADDRESS;
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC20,
erc20Proxy.address,
prevProxyAddress,
{ from: notOwner },
),
+ RevertReasons.OnlyContractOwner,
);
});
it('should throw if attempting to register a proxy to the incorrect id', async () => {
const prevProxyAddress = constants.NULL_ADDRESS;
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC721,
erc20Proxy.address,
prevProxyAddress,
{ from: owner },
),
+ RevertReasons.AssetProxyIdMismatch,
);
});
});
@@ -305,7 +311,7 @@ describe('AssetProxyDispatcher', () => {
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync(
encodedAssetData,
makerAddress,
@@ -313,6 +319,7 @@ describe('AssetProxyDispatcher', () => {
amount,
{ from: owner },
),
+ RevertReasons.AssetProxyDoesNotExist,
);
});
});
diff --git a/packages/contracts/test/exchange/fill_order.ts b/packages/contracts/test/exchange/fill_order.ts
new file mode 100644
index 000000000..60fe777c3
--- /dev/null
+++ b/packages/contracts/test/exchange/fill_order.ts
@@ -0,0 +1,285 @@
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+
+import { chaiSetup } from '../../src/utils/chai_setup';
+import { CoreCombinatorialUtils, coreCombinatorialUtilsFactoryAsync } from '../../src/utils/core_combinatorial_utils';
+import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
+
+import {
+ AllowanceAmountScenario,
+ AssetDataScenario,
+ BalanceAmountScenario,
+ ExpirationTimeSecondsScenario,
+ FeeRecipientAddressScenario,
+ OrderAssetAmountScenario,
+ TakerAssetFillAmountScenario,
+ TakerScenario,
+} from '../../src/utils/types';
+
+chaiSetup.configure();
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+const defaultFillScenario = {
+ orderScenario: {
+ takerScenario: TakerScenario.Unspecified,
+ feeRecipientScenario: FeeRecipientAddressScenario.EthUserAddress,
+ makerAssetAmountScenario: OrderAssetAmountScenario.Large,
+ takerAssetAmountScenario: OrderAssetAmountScenario.Large,
+ makerFeeScenario: OrderAssetAmountScenario.Large,
+ takerFeeScenario: OrderAssetAmountScenario.Large,
+ expirationTimeSecondsScenario: ExpirationTimeSecondsScenario.InFuture,
+ makerAssetDataScenario: AssetDataScenario.ERC20NonZRXEighteenDecimals,
+ takerAssetDataScenario: AssetDataScenario.ERC20NonZRXEighteenDecimals,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.LessThanRemainingFillableTakerAssetAmount,
+ makerStateScenario: {
+ traderAssetBalance: BalanceAmountScenario.Higher,
+ traderAssetAllowance: AllowanceAmountScenario.Higher,
+ zrxFeeBalance: BalanceAmountScenario.Higher,
+ zrxFeeAllowance: AllowanceAmountScenario.Higher,
+ },
+ takerStateScenario: {
+ traderAssetBalance: BalanceAmountScenario.Higher,
+ traderAssetAllowance: AllowanceAmountScenario.Higher,
+ zrxFeeBalance: BalanceAmountScenario.Higher,
+ zrxFeeAllowance: AllowanceAmountScenario.Higher,
+ },
+};
+
+describe('FillOrder Tests', () => {
+ let coreCombinatorialUtils: CoreCombinatorialUtils;
+
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ coreCombinatorialUtils = await coreCombinatorialUtilsFactoryAsync(web3Wrapper, txDefaults);
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('fillOrder', () => {
+ it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ takerAssetAmountScenario: OrderAssetAmountScenario.Small,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetAmountScenario: OrderAssetAmountScenario.Small,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ takerScenario: TakerScenario.CorrectlySpecified,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ it('should fill remaining value if takerAssetFillAmount > remaining takerAssetAmount', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ it('should throw when taker is specified and order is claimed by other', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ takerScenario: TakerScenario.IncorrectlySpecified,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if makerAssetAmount is 0', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetAmountScenario: OrderAssetAmountScenario.Zero,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if takerAssetAmount is 0', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ takerAssetAmountScenario: OrderAssetAmountScenario.Zero,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if takerAssetFillAmount is 0', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.Zero,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if an order is expired', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ expirationTimeSecondsScenario: ExpirationTimeSecondsScenario.InPast,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if maker erc20Balances are too low to fill order', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ makerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetBalance: BalanceAmountScenario.TooLow,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if taker erc20Balances are too low to fill order', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ takerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetBalance: BalanceAmountScenario.TooLow,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if maker allowances are too low to fill order', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ makerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetAllowance: AllowanceAmountScenario.TooLow,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should throw if taker allowances are too low to fill order', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ takerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetAllowance: AllowanceAmountScenario.TooLow,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ });
+
+ describe('Testing Exchange of ERC721 Tokens', () => {
+ it('should successfully exchange a single token between the maker and taker (via fillOrder)', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetDataScenario: AssetDataScenario.ERC721,
+ takerAssetDataScenario: AssetDataScenario.ERC721,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should successfully fill order when makerAsset is ERC721 and takerAsset is ERC20', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetDataScenario: AssetDataScenario.ERC721,
+ takerAssetDataScenario: AssetDataScenario.ERC20NonZRXEighteenDecimals,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario, true);
+ });
+
+ it('should successfully fill order when makerAsset is ERC20 and takerAsset is ERC721', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetDataScenario: AssetDataScenario.ERC20NonZRXEighteenDecimals,
+ takerAssetDataScenario: AssetDataScenario.ERC721,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyRemainingFillableTakerAssetAmount,
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should successfully fill order when makerAsset is ERC721 and approveAll is set for it', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetDataScenario: AssetDataScenario.ERC721,
+ takerAssetDataScenario: AssetDataScenario.ERC20NonZRXEighteenDecimals,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyRemainingFillableTakerAssetAmount,
+ makerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetAllowance: AllowanceAmountScenario.Unlimited,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+
+ it('should successfully fill order when makerAsset and takerAsset are ERC721 and approveAll is set for them', async () => {
+ const fillScenario = {
+ ...defaultFillScenario,
+ orderScenario: {
+ ...defaultFillScenario.orderScenario,
+ makerAssetDataScenario: AssetDataScenario.ERC721,
+ takerAssetDataScenario: AssetDataScenario.ERC721,
+ },
+ takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyRemainingFillableTakerAssetAmount,
+ makerStateScenario: {
+ ...defaultFillScenario.makerStateScenario,
+ traderAssetAllowance: AllowanceAmountScenario.Unlimited,
+ },
+ takerStateScenario: {
+ ...defaultFillScenario.takerStateScenario,
+ traderAssetAllowance: AllowanceAmountScenario.Unlimited,
+ },
+ };
+ await coreCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
+ });
+ });
+});
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts
index 18a46187f..7c4ad165e 100644
--- a/packages/contracts/test/exchange/match_orders.ts
+++ b/packages/contracts/test/exchange/match_orders.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
-import { AssetProxyId } from '@0xproject/types';
+import { AssetProxyId, RevertReasons } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -12,7 +12,7 @@ import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c2
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
+import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -81,7 +81,10 @@ describe('matchOrders', () => {
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
// Deploy ERC20 token & ERC20 proxy
- [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync();
+ [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ constants.NUM_DUMMY_ERC20_TO_DEPLOY,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
// Deploy ERC721 token and proxy
@@ -598,8 +601,9 @@ describe('matchOrders', () => {
// Cancel left order
await exchangeWrapper.cancelOrderAsync(signedOrderLeft, signedOrderLeft.makerAddress);
// Match orders
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -622,8 +626,9 @@ describe('matchOrders', () => {
// Cancel right order
await exchangeWrapper.cancelOrderAsync(signedOrderRight, signedOrderRight.makerAddress);
// Match orders
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -644,7 +649,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight,
});
// Match orders
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
@@ -652,6 +657,7 @@ describe('matchOrders', () => {
erc20BalancesByOwner,
erc721TokenIdsByOwner,
),
+ RevertReasons.NegativeSpreadRequired,
);
});
@@ -672,7 +678,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight,
});
// Match orders
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
@@ -680,6 +686,11 @@ describe('matchOrders', () => {
erc20BalancesByOwner,
erc721TokenIdsByOwner,
),
+ // We are assuming assetData fields of the right order are the
+ // reverse of the left order, rather than checking equality. This
+ // saves a bunch of gas, but as a result if the assetData fields are
+ // off then the failure ends up happening at signature validation
+ RevertReasons.InvalidOrderSignature,
);
});
@@ -702,7 +713,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight,
});
// Match orders
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
@@ -710,6 +721,7 @@ describe('matchOrders', () => {
erc20BalancesByOwner,
erc721TokenIdsByOwner,
),
+ RevertReasons.InvalidOrderSignature,
);
});
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index 8e221e3f1..c610ead61 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { addSignedMessagePrefix, assetProxyUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
-import { SignatureType, SignedOrder } from '@0xproject/types';
+import { RevertReasons, SignatureType, SignedOrder } from '@0xproject/types';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
@@ -107,7 +107,7 @@ describe('MixinSignatureValidator', () => {
signedOrder.makerAddress,
emptySignature,
),
- constants.EXCHANGE_LENGTH_GREATER_THAN_0_REQUIRED,
+ RevertReasons.LengthGreaterThan0Required,
);
});
@@ -121,7 +121,7 @@ describe('MixinSignatureValidator', () => {
signedOrder.makerAddress,
unsupportedSignatureHex,
),
- constants.EXCHANGE_SIGNATURE_UNSUPPORTED,
+ RevertReasons.SignatureUnsupported,
);
});
@@ -134,7 +134,7 @@ describe('MixinSignatureValidator', () => {
signedOrder.makerAddress,
unsupportedSignatureHex,
),
- constants.EXCHANGE_SIGNATURE_ILLEGAL,
+ RevertReasons.SignatureIllegal,
);
});
@@ -161,7 +161,7 @@ describe('MixinSignatureValidator', () => {
signedOrder.makerAddress,
signatureHex,
),
- constants.EXCHANGE_LENGTH_0_REQUIRED,
+ RevertReasons.Length0Required,
);
});
diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts
index 43b9f46b2..cfabe0435 100644
--- a/packages/contracts/test/exchange/transactions.ts
+++ b/packages/contracts/test/exchange/transactions.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
-import { AssetProxyId, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
+import { AssetProxyId, OrderWithoutExchangeAddress, RevertReasons, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -10,7 +10,7 @@ import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange
import { ExchangeWrapperContract } from '../../src/generated_contract_wrappers/exchange_wrapper';
import { WhitelistContract } from '../../src/generated_contract_wrappers/whitelist';
import { artifacts } from '../../src/utils/artifacts';
-import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
+import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -59,13 +59,22 @@ describe('Exchange transactions', () => {
after(async () => {
await blockchainLifecycle.revertAsync();
});
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, senderAddress, makerAddress, takerAddress, feeRecipientAddress] = accounts);
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
- [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync();
+ [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ constants.NUM_DUMMY_ERC20_TO_DEPLOY,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
@@ -101,13 +110,6 @@ describe('Exchange transactions', () => {
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address);
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address);
});
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
describe('executeTransaction', () => {
describe('fillOrder', () => {
let takerAssetFillAmount: BigNumber;
@@ -126,8 +128,9 @@ describe('Exchange transactions', () => {
});
it('should throw if not called by specified sender', async () => {
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.executeTransactionAsync(signedTx, takerAddress),
+ RevertReasons.FailedExecution,
);
});
@@ -168,8 +171,9 @@ describe('Exchange transactions', () => {
it('should throw if the a 0x transaction with the same transactionHash has already been executed', async () => {
await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.executeTransactionAsync(signedTx, senderAddress),
+ RevertReasons.InvalidTxHash,
);
});
@@ -187,15 +191,17 @@ describe('Exchange transactions', () => {
});
it('should throw if not called by specified sender', async () => {
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.executeTransactionAsync(signedTx, makerAddress),
+ RevertReasons.FailedExecution,
);
});
it('should cancel the order when signed by maker and called by sender', async () => {
await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, senderAddress),
+ RevertReasons.OrderUnfillable,
);
});
});
@@ -238,7 +244,7 @@ describe('Exchange transactions', () => {
signedOrder.signature,
);
const signedFillTx = takerTransactionFactory.newSignedTransaction(fillData);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapperContract.fillOrder.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
@@ -247,6 +253,7 @@ describe('Exchange transactions', () => {
signedFillTx.signature,
{ from: takerAddress },
),
+ RevertReasons.FailedExecution,
);
});
@@ -357,7 +364,7 @@ describe('Exchange transactions', () => {
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt();
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
@@ -365,6 +372,7 @@ describe('Exchange transactions', () => {
signedOrder.signature,
{ from: takerAddress },
),
+ RevertReasons.MakerNotWhitelisted,
);
});
@@ -378,7 +386,7 @@ describe('Exchange transactions', () => {
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt();
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
@@ -386,6 +394,7 @@ describe('Exchange transactions', () => {
signedOrder.signature,
{ from: takerAddress },
),
+ RevertReasons.TakerNotWhitelisted,
);
});
diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts
index a39a81057..7e3203291 100644
--- a/packages/contracts/test/exchange/wrapper.ts
+++ b/packages/contracts/test/exchange/wrapper.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
-import { AssetProxyId, SignedOrder } from '@0xproject/types';
+import { AssetProxyId, RevertReasons, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -12,7 +12,7 @@ import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c2
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange';
import { artifacts } from '../../src/utils/artifacts';
-import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
+import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -65,7 +65,10 @@ describe('Exchange wrappers', () => {
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync();
+ [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
+ constants.NUM_DUMMY_ERC20_TO_DEPLOY,
+ constants.DUMMY_TOKEN_DECIMALS,
+ );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
@@ -165,13 +168,14 @@ describe('Exchange wrappers', () => {
);
});
- it('should throw if an signedOrder is expired', async () => {
+ it('should throw if a signedOrder is expired', async () => {
const signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
});
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress),
+ RevertReasons.OrderUnfillable,
);
});
@@ -182,8 +186,9 @@ describe('Exchange wrappers', () => {
takerAssetFillAmount: signedOrder.takerAssetAmount.div(2),
});
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress),
+ RevertReasons.CompleteFillFailed,
);
});
});
@@ -368,7 +373,7 @@ describe('Exchange wrappers', () => {
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
- gas: 270000,
+ gas: 280000,
});
// Verify post-conditions
const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -494,10 +499,11 @@ describe('Exchange wrappers', () => {
await exchangeWrapper.fillOrKillOrderAsync(signedOrders[0], takerAddress);
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.batchFillOrKillOrdersAsync(signedOrders, takerAddress, {
takerAssetFillAmounts,
}),
+ RevertReasons.OrderUnfillable,
);
});
});
@@ -687,7 +693,7 @@ describe('Exchange wrappers', () => {
expect(newBalances).to.be.deep.equal(erc20Balances);
});
- it('should throw when an signedOrder does not use the same takerAssetAddress', async () => {
+ it('should throw when a signedOrder does not use the same takerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
@@ -696,10 +702,13 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(),
];
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketSellOrdersAsync(signedOrders, takerAddress, {
takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}),
+ // We simply use the takerAssetData from the first order for all orders.
+ // If they are not the same, the contract throws when validating the order signature
+ RevertReasons.InvalidOrderSignature,
);
});
});
@@ -902,7 +911,7 @@ describe('Exchange wrappers', () => {
expect(newBalances).to.be.deep.equal(erc20Balances);
});
- it('should throw when an signedOrder does not use the same makerAssetAddress', async () => {
+ it('should throw when a signedOrder does not use the same makerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
@@ -911,10 +920,11 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(),
];
- return expectRevertOrAlwaysFailingTransactionAsync(
+ return expectRevertReasonOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketBuyOrdersAsync(signedOrders, takerAddress, {
makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}),
+ RevertReasons.InvalidOrderSignature,
);
});
});