aboutsummaryrefslogtreecommitdiffstats
path: root/contracts/extensions/test
diff options
context:
space:
mode:
authorHsuan Lee <hsuan@cobinhood.com>2019-01-19 18:42:04 +0800
committerHsuan Lee <hsuan@cobinhood.com>2019-01-19 18:42:04 +0800
commit7ae38906926dc09bc10670c361af0d2bf0050426 (patch)
tree5fb10ae366b987db09e4ddb4bc3ba0f75404ad08 /contracts/extensions/test
parentb5fd3c72a08aaa6957917d74c333387a16edf66b (diff)
downloaddexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.gz
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.bz2
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.lz
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.xz
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.zst
dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.zip
Update dependency packages
Diffstat (limited to 'contracts/extensions/test')
-rw-r--r--contracts/extensions/test/extensions/balance_threshold_filter.ts1644
-rw-r--r--contracts/extensions/test/extensions/dutch_auction.ts378
-rw-r--r--contracts/extensions/test/extensions/forwarder.ts1291
-rw-r--r--contracts/extensions/test/extensions/order_matcher.ts818
-rw-r--r--contracts/extensions/test/extensions/order_validator.ts609
-rw-r--r--contracts/extensions/test/global_hooks.ts17
-rw-r--r--contracts/extensions/test/utils/balance_threshold_wrapper.ts283
-rw-r--r--contracts/extensions/test/utils/dutch_auction_test_wrapper.ts62
-rw-r--r--contracts/extensions/test/utils/forwarder_wrapper.ts124
9 files changed, 0 insertions, 5226 deletions
diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts
deleted file mode 100644
index adeb7c422..000000000
--- a/contracts/extensions/test/extensions/balance_threshold_filter.ts
+++ /dev/null
@@ -1,1644 +0,0 @@
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { assetDataUtils } from '@0x/order-utils';
-import { Order, RevertReason, SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import * as chai from 'chai';
-import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import {
- artifacts as protocolArtifacts,
- ERC20Wrapper,
- ERC721Wrapper,
- ExchangeContract,
- ExchangeWrapper,
-} from '@0x/contracts-protocol';
-import {
- chaiSetup,
- constants,
- ContractName,
- ERC20BalancesByOwner,
- expectTransactionFailedAsync,
- OrderFactory,
- OrderStatus,
- provider,
- TransactionFactory,
- txDefaults,
- web3Wrapper,
-} from '@0x/contracts-test-utils';
-import { DummyERC20TokenContract } from '@0x/contracts-tokens';
-
-import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter';
-import { artifacts } from '../../src/artifacts';
-import { BalanceThresholdWrapper } from '../utils/balance_threshold_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-const DECIMALS_DEFAULT = 18;
-
-interface ValidatedAddressesLog {
- args: { addresses: string[] };
-}
-
-describe(ContractName.BalanceThresholdFilter, () => {
- const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT);
- const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT);
- const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT);
-
- let validMakerAddress: string;
- let validMakerAddress2: string;
- let owner: string;
- let validTakerAddress: string;
- let feeRecipientAddress: string;
- let invalidAddress: string;
- let defaultMakerAssetAddress: string;
- let defaultTakerAssetAddress: string;
- let zrxAssetData: string;
- let zrxToken: DummyERC20TokenContract;
- let exchangeInstance: ExchangeContract;
- let exchangeWrapper: ExchangeWrapper;
-
- let orderFactory: OrderFactory;
- let orderFactory2: OrderFactory;
- let invalidOrderFactory: OrderFactory;
- let erc20Wrapper: ERC20Wrapper;
- let erc20Balances: ERC20BalancesByOwner;
- let erc20TakerBalanceThresholdWrapper: BalanceThresholdWrapper;
- let erc721TakerBalanceThresholdWrapper: BalanceThresholdWrapper;
- let erc721MakerBalanceThresholdWrapper: BalanceThresholdWrapper;
- let erc721NonValidBalanceThresholdWrapper: BalanceThresholdWrapper;
-
- let defaultOrderParams: Partial<Order>;
- let validSignedOrder: SignedOrder;
- let validSignedOrder2: SignedOrder;
-
- let erc721BalanceThresholdFilterInstance: BalanceThresholdFilterContract;
- let erc20BalanceThresholdFilterInstance: BalanceThresholdFilterContract;
-
- const assertValidatedAddressesLog = async (
- txReceipt: TransactionReceiptWithDecodedLogs,
- expectedValidatedAddresses: string[],
- ) => {
- expect(txReceipt.logs.length).to.be.gte(1);
- const validatedAddressesLog = (txReceipt.logs[0] as any) as ValidatedAddressesLog;
- const validatedAddresses = validatedAddressesLog.args.addresses;
- // @HACK-hysz: Nested addresses are not translated to lower-case but this will change once
- // the new ABI Encoder/Decoder is used by the contract templates.
- const validatedAddressesNormalized: string[] = [];
- _.each(validatedAddresses, address => {
- const normalizedAddress = _.toLower(address);
- validatedAddressesNormalized.push(normalizedAddress);
- });
- expect(validatedAddressesNormalized).to.be.deep.equal(expectedValidatedAddresses);
- };
-
- before(async () => {
- // Create accounts
- await blockchainLifecycle.startAsync();
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const usedAddresses = ([
- owner,
- validMakerAddress,
- validMakerAddress2,
- validTakerAddress,
- feeRecipientAddress,
- invalidAddress,
- ] = accounts);
- const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validTakerAddress)];
- const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress)];
- const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress2)];
- const invalidAddressPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(invalidAddress)];
- // Create wrappers
- erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
- const validAddresses = _.cloneDeepWith(usedAddresses);
- _.remove(validAddresses, (address: string) => {
- return address === invalidAddress;
- });
- const erc721Wrapper = new ERC721Wrapper(provider, validAddresses, owner);
- // Deploy ERC20 tokens
- const numDummyErc20ToDeploy = 4;
- let erc20TokenA: DummyERC20TokenContract;
- let erc20TokenB: DummyERC20TokenContract;
- let erc20BalanceThresholdAsset: DummyERC20TokenContract;
- [erc20TokenA, erc20TokenB, zrxToken, erc20BalanceThresholdAsset] = await erc20Wrapper.deployDummyTokensAsync(
- numDummyErc20ToDeploy,
- constants.DUMMY_TOKEN_DECIMALS,
- );
- defaultMakerAssetAddress = erc20TokenA.address;
- defaultTakerAssetAddress = erc20TokenB.address;
- zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- // Create proxies
- const erc20Proxy = await erc20Wrapper.deployProxyAsync();
- await erc20Wrapper.setBalancesAndAllowancesAsync();
- // Deploy Exchange contract
- exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- zrxAssetData,
- );
- exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
- // Register proxies
- await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
- await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
- from: owner,
- });
- // Deploy Balance Threshold Filters
- // One uses an ERC721 token as its balance threshold asset; the other uses an ERC20
- const erc721alanceThreshold = new BigNumber(1);
- await erc721Wrapper.deployProxyAsync();
- const [erc721BalanceThresholdAsset] = await erc721Wrapper.deployDummyTokensAsync();
- await erc721Wrapper.setBalancesAndAllowancesAsync();
- erc721BalanceThresholdFilterInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync(
- artifacts.BalanceThresholdFilter,
- provider,
- txDefaults,
- exchangeInstance.address,
- erc721BalanceThresholdAsset.address,
- erc721alanceThreshold,
- );
- const erc20BalanceThreshold = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 10);
- erc20BalanceThresholdFilterInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync(
- artifacts.BalanceThresholdFilter,
- provider,
- txDefaults,
- exchangeInstance.address,
- erc20BalanceThresholdAsset.address,
- erc20BalanceThreshold,
- );
- // Default order parameters
- defaultOrderParams = {
- exchangeAddress: exchangeInstance.address,
- feeRecipientAddress,
- makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
- makerAssetAmount,
- takerAssetAmount,
- makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS_DEFAULT),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(150), DECIMALS_DEFAULT),
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- };
- // Create two order factories with valid makers (who meet the threshold balance), and
- // one factory for an invalid address (that does not meet the threshold balance)
- // Valid order factory #1
- const defaultOrderParams1 = {
- makerAddress: validMakerAddress,
- ...defaultOrderParams,
- };
- orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams1);
- // Valid order factory #2
- const defaultOrderParams2 = {
- makerAddress: validMakerAddress2,
- ...defaultOrderParams,
- };
- orderFactory2 = new OrderFactory(secondMakerPrivateKey, defaultOrderParams2);
- // Invalid order factory
- const defaultNonValidOrderParams = {
- makerAddress: invalidAddress,
- ...defaultOrderParams,
- };
- invalidOrderFactory = new OrderFactory(invalidAddressPrivateKey, defaultNonValidOrderParams);
- // Create Balance Thresold Wrappers
- erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
- erc20BalanceThresholdFilterInstance,
- exchangeInstance,
- new TransactionFactory(takerPrivateKey, exchangeInstance.address),
- provider,
- );
- erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
- erc721BalanceThresholdFilterInstance,
- exchangeInstance,
- new TransactionFactory(takerPrivateKey, exchangeInstance.address),
- provider,
- );
- erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper(
- erc721BalanceThresholdFilterInstance,
- exchangeInstance,
- new TransactionFactory(makerPrivateKey, exchangeInstance.address),
- provider,
- );
- erc721NonValidBalanceThresholdWrapper = new BalanceThresholdWrapper(
- erc721BalanceThresholdFilterInstance,
- exchangeInstance,
- new TransactionFactory(invalidAddressPrivateKey, exchangeInstance.address),
- provider,
- );
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
- describe('General Sanity Checks', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both maker/taker when both maker and taker exceed the balance threshold of an ERC20 token', async () => {
- const validSignedOrderERC20Sender = await orderFactory.newSignedOrderAsync({
- ...defaultOrderParams,
- makerAddress: validMakerAddress,
- senderAddress: erc20TakerBalanceThresholdWrapper.getBalanceThresholdAddress(),
- });
- // Execute a valid fill
- const txReceipt = await erc20TakerBalanceThresholdWrapper.fillOrderAsync(
- validSignedOrderERC20Sender,
- validTakerAddress,
- { takerAssetFillAmount },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.plus(takerFeePaid)),
- );
- });
- it('should revert if the Exchange transaction function is not supported', async () => {
- // Create signed order without the fillOrder function selector
- const salt = new BigNumber(0);
- const badSelectorHex = '0x00000000';
- const signatureHex = '0x';
- // Call valid forwarder
- return expectTransactionFailedAsync(
- erc721BalanceThresholdFilterInstance.executeTransaction.sendTransactionAsync(
- salt,
- validTakerAddress,
- badSelectorHex,
- signatureHex,
- ),
- RevertReason.InvalidOrBlockedExchangeSelector,
- );
- });
- it('should revert if senderAddress is not set to the valid forwarding contract', async () => {
- // Create signed order with incorrect senderAddress
- const notBalanceThresholdFilterAddress = zrxToken.address;
- const signedOrderWithBadSenderAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: notBalanceThresholdFilterAddress,
- });
- // Call valid forwarder
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.fillOrderAsync(signedOrderWithBadSenderAddress, validTakerAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.FailedExecution,
- );
- });
- });
-
- describe('batchFillOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, validTakerAddress, {
- takerAssetFillAmounts,
- });
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2);
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount)
- .times(2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
-
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount.times(2)),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.times(2).plus(takerFeePaid)),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, validTakerAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.batchFillOrdersAsync(orders, invalidAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('batchFillOrdersNoThrow', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(
- orders,
- validTakerAddress,
- {
- takerAssetFillAmounts,
- // 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: 600000,
- },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2);
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount)
- .times(2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
-
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount.times(2)),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.times(2).plus(takerFeePaid)),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, validTakerAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, invalidAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('batchFillOrKillOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(
- orders,
- validTakerAddress,
- { takerAssetFillAmounts },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2);
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount)
- .times(2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
-
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount.times(2)),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.times(2).plus(takerFeePaid)),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, validTakerAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount];
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, invalidAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if one takerAssetFillAmount is not fully filled', async () => {
- const tooBigTakerAssetFillAmount = validSignedOrder.takerAssetAmount.times(2);
- const orders = [validSignedOrder, validSignedOrder2];
- const takerAssetFillAmounts = [takerAssetFillAmount, tooBigTakerAssetFillAmount];
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, validTakerAddress, {
- takerAssetFillAmounts,
- }),
- RevertReason.FailedExecution,
- );
- });
- });
-
- describe('fillOrder', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderAsync(
- validSignedOrder,
- validTakerAddress,
- { takerAssetFillAmount },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.plus(takerFeePaid)),
- );
- });
- it('should revert if maker does not meet the balance threshold', async () => {
- // Create signed order with non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- makerAddress: invalidAddress,
- });
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.fillOrderAsync(signedOrderWithBadMakerAddress, validTakerAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.fillOrderAsync(validSignedOrder, invalidAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('fillOrderNoThrow', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync(
- validSignedOrder,
- validTakerAddress,
- {
- takerAssetFillAmount,
- // 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: 600000,
- },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.plus(takerFeePaid)),
- );
- });
- it('should revert if maker does not meet the balance threshold', async () => {
- // Create signed order with non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- makerAddress: invalidAddress,
- });
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync(
- signedOrderWithBadMakerAddress,
- validTakerAddress,
- { takerAssetFillAmount },
- ),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.fillOrderNoThrowAsync(validSignedOrder, invalidAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('fillOrKillOrder', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const takerAssetFillAmount_ = validSignedOrder.takerAssetAmount;
- const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(
- validSignedOrder,
- validTakerAddress,
- { takerAssetFillAmount: takerAssetFillAmount_ },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount = takerAssetFillAmount_
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid = validSignedOrder.makerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee
- .times(makerAssetFillAmount)
- .dividedToIntegerBy(validSignedOrder.makerAssetAmount);
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(takerAssetFillAmount_),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid),
- );
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount_),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(makerFeePaid.plus(takerFeePaid)),
- );
- });
- it('should revert if maker does not meet the balance threshold', async () => {
- // Create signed order with non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- makerAddress: invalidAddress,
- });
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(
- signedOrderWithBadMakerAddress,
- validTakerAddress,
- { takerAssetFillAmount },
- ),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.fillOrKillOrderAsync(validSignedOrder, invalidAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if takerAssetFillAmount is not fully filled', async () => {
- const tooBigTakerAssetFillAmount = validSignedOrder.takerAssetAmount.times(2);
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(validSignedOrder, validTakerAddress, {
- takerAssetFillAmount: tooBigTakerAssetFillAmount,
- }),
- RevertReason.FailedExecution,
- );
- });
- });
-
- describe('marketSellOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount);
- const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(
- orders,
- validTakerAddress,
- { takerAssetFillAmount: cumulativeTakerAssetFillAmount },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount2 = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid2 = validSignedOrder2.makerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid2 = validSignedOrder2.takerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2);
- const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(validSignedOrder.takerAssetAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(cumulativeMakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address]
- .plus(validSignedOrder.makerFee)
- .plus(makerFeePaid2)
- .plus(takerFeePaid),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, validTakerAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.marketSellOrdersAsync(orders, invalidAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('marketSellOrdersNoThrow', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount);
- const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(
- orders,
- validTakerAddress,
- {
- takerAssetFillAmount: cumulativeTakerAssetFillAmount,
- // 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: 600000,
- },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerAssetFillAmount2 = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const makerFeePaid2 = validSignedOrder2.makerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid2 = validSignedOrder2.takerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2);
- const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(validSignedOrder.takerAssetAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(cumulativeMakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address]
- .plus(validSignedOrder.makerFee)
- .plus(makerFeePaid2)
- .plus(takerFeePaid),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, validTakerAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, invalidAddress, {
- takerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('marketBuyOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount);
- const makerAssetFillAmount2 = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2);
- const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, validTakerAddress, {
- makerAssetFillAmount: cumulativeMakerAssetFillAmount,
- });
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerFeePaid2 = validSignedOrder2.makerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid2 = validSignedOrder2.takerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(validSignedOrder.takerAssetAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(cumulativeMakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address]
- .plus(validSignedOrder.makerFee)
- .plus(makerFeePaid2)
- .plus(takerFeePaid),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- const dummyMakerAssetFillAmount = new BigNumber(0);
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, validTakerAddress, {
- makerAssetFillAmount: dummyMakerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- const dummyMakerAssetFillAmount = new BigNumber(0);
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.marketBuyOrdersAsync(orders, invalidAddress, {
- makerAssetFillAmount: dummyMakerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('marketBuyOrdersNoThrowAsync', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => {
- // Execute a valid fill
- const orders = [validSignedOrder, validSignedOrder2];
- const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount);
- const makerAssetFillAmount2 = takerAssetFillAmount
- .times(validSignedOrder.makerAssetAmount)
- .dividedToIntegerBy(validSignedOrder.takerAssetAmount);
- const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2);
- const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(
- orders,
- validTakerAddress,
- {
- makerAssetFillAmount: cumulativeMakerAssetFillAmount,
- // 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: 600000,
- },
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- validSignedOrder.makerAddress,
- validSignedOrder2.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const makerFeePaid2 = validSignedOrder2.makerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid2 = validSignedOrder2.takerFee
- .times(makerAssetFillAmount2)
- .dividedToIntegerBy(validSignedOrder2.makerAssetAmount);
- const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2);
- // Maker #1
- expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount),
- );
- expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][defaultTakerAssetAddress].plus(validSignedOrder.takerAssetAmount),
- );
- expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee),
- );
- // Maker #2
- expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2),
- );
- expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][defaultTakerAssetAddress].plus(takerAssetFillAmount),
- );
- expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2),
- );
- // Taker
- expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(cumulativeMakerAssetFillAmount),
- );
- expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid),
- );
- // Fee recipient
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address]
- .plus(validSignedOrder.makerFee)
- .plus(makerFeePaid2)
- .plus(takerFeePaid),
- );
- });
- it('should revert if one maker does not meet the balance threshold', async () => {
- // Create order set with one non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- makerAddress: invalidAddress,
- });
- const orders = [validSignedOrder, signedOrderWithBadMakerAddress];
- // Execute transaction
- const dummyMakerAssetFillAmount = new BigNumber(0);
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, validTakerAddress, {
- makerAssetFillAmount: dummyMakerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- const orders = [validSignedOrder, validSignedOrder2];
- const dummyMakerAssetFillAmount = new BigNumber(0);
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, invalidAddress, {
- makerAssetFillAmount: dummyMakerAssetFillAmount,
- }),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('matchOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('Should transfer correct amounts when both makers and taker meet the balance threshold', async () => {
- // Test values/results taken from Match Orders test:
- // 'Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil'
- // Create orders to match
- const signedOrderLeft = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(17), 0),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(98), 0),
- makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
- feeRecipientAddress,
- });
- const signedOrderRight = await orderFactory2.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
- takerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0),
- makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
- feeRecipientAddress,
- });
- // Compute expected transfer amounts
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0),
- amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0),
- feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.4705882352941176'), 16), // 76.47%
- // Right Maker
- amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0),
- amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0),
- feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100%
- // Taker
- amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 0),
- feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53%
- feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100%
- };
- const txReceipt = await erc721TakerBalanceThresholdWrapper.matchOrdersAsync(
- signedOrderLeft,
- signedOrderRight,
- validTakerAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses = [
- signedOrderLeft.makerAddress,
- signedOrderRight.makerAddress,
- validTakerAddress,
- ];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check balances
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(
- newBalances[signedOrderLeft.makerAddress][defaultMakerAssetAddress],
- 'Checking left maker egress ERC20 account balance',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderLeft.makerAddress][defaultMakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(
- newBalances[signedOrderRight.makerAddress][defaultTakerAssetAddress],
- 'Checking right maker ingress ERC20 account balance',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderRight.makerAddress][defaultTakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(
- newBalances[validTakerAddress][defaultMakerAssetAddress],
- 'Checking taker ingress ERC20 account balance',
- ).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][defaultMakerAssetAddress].plus(
- expectedTransferAmounts.amountReceivedByTaker,
- ),
- );
- expect(
- newBalances[signedOrderLeft.makerAddress][defaultTakerAssetAddress],
- 'Checking left maker ingress ERC20 account balance',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderLeft.makerAddress][defaultTakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(
- newBalances[signedOrderRight.makerAddress][defaultMakerAssetAddress],
- 'Checking right maker egress ERC20 account balance',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderRight.makerAddress][defaultMakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- // Paid fees
- expect(
- newBalances[signedOrderLeft.makerAddress][zrxToken.address],
- 'Checking left maker egress ERC20 account fees',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderLeft.makerAddress][zrxToken.address].minus(
- expectedTransferAmounts.feePaidByLeftMaker,
- ),
- );
- expect(
- newBalances[signedOrderRight.makerAddress][zrxToken.address],
- 'Checking right maker egress ERC20 account fees',
- ).to.be.bignumber.equal(
- erc20Balances[signedOrderRight.makerAddress][zrxToken.address].minus(
- expectedTransferAmounts.feePaidByRightMaker,
- ),
- );
- expect(
- newBalances[validTakerAddress][zrxToken.address],
- 'Checking taker egress ERC20 account fees',
- ).to.be.bignumber.equal(
- erc20Balances[validTakerAddress][zrxToken.address]
- .minus(expectedTransferAmounts.feePaidByTakerLeft)
- .minus(expectedTransferAmounts.feePaidByTakerRight),
- );
- // Received fees
- expect(
- newBalances[signedOrderLeft.feeRecipientAddress][zrxToken.address],
- 'Checking left fee recipient ingress ERC20 account fees',
- ).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address]
- .plus(expectedTransferAmounts.feePaidByLeftMaker)
- .plus(expectedTransferAmounts.feePaidByRightMaker)
- .plus(expectedTransferAmounts.feePaidByTakerLeft)
- .plus(expectedTransferAmounts.feePaidByTakerRight),
- );
- });
- it('should revert if left maker does not meet the balance threshold', async () => {
- // Create signed order with non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- makerAddress: invalidAddress,
- });
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.matchOrdersAsync(
- validSignedOrder,
- signedOrderWithBadMakerAddress,
- validTakerAddress,
- ),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if right maker does not meet the balance threshold', async () => {
- // Create signed order with non-valid maker address
- const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
- senderAddress: erc721BalanceThresholdFilterInstance.address,
- makerAddress: invalidAddress,
- });
- // Execute transaction
- return expectTransactionFailedAsync(
- erc721TakerBalanceThresholdWrapper.matchOrdersAsync(
- signedOrderWithBadMakerAddress,
- validSignedOrder,
- validTakerAddress,
- ),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- it('should revert if taker does not meet the balance threshold', async () => {
- return expectTransactionFailedAsync(
- erc721NonValidBalanceThresholdWrapper.matchOrdersAsync(
- validSignedOrder,
- validSignedOrder,
- invalidAddress,
- ),
- RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold,
- );
- });
- });
-
- describe('cancelOrder', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- validSignedOrder = await orderFactory.newSignedOrderAsync();
- validSignedOrder2 = await orderFactory2.newSignedOrderAsync();
- });
- it('Should successfully cancel order if maker meets balance threshold', async () => {
- // Verify order is not cancelled
- const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- validSignedOrder,
- );
- expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- // Cancel
- const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrderAsync(
- validSignedOrder,
- validSignedOrder.makerAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- validSignedOrder,
- );
- expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- });
- it('Should successfully cancel order if maker does not meet balance threshold', async () => {
- // Create order where maker does not meet balance threshold
- const signedOrderWithBadMakerAddress = await invalidOrderFactory.newSignedOrderAsync({});
- // Verify order is not cancelled
- const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrderWithBadMakerAddress,
- );
- expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- // Cancel
- const txReceipt = await erc721NonValidBalanceThresholdWrapper.cancelOrderAsync(
- signedOrderWithBadMakerAddress,
- signedOrderWithBadMakerAddress.makerAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrderWithBadMakerAddress,
- );
- expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- });
- });
-
- describe('batchCancelOrders', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- });
- it('Should successfully batch cancel orders if maker meets balance threshold', async () => {
- // Create orders to cancel
- const validSignedOrders = [
- await orderFactory.newSignedOrderAsync(),
- await orderFactory.newSignedOrderAsync(),
- await orderFactory.newSignedOrderAsync(),
- ];
- // Verify orders are not cancelled
- _.each(validSignedOrders, async signedOrder => {
- const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- });
- // Cancel
- const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync(
- validSignedOrders,
- validSignedOrders[0].makerAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- _.each(validSignedOrders, async signedOrder => {
- const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- });
- });
- it('Should successfully batch cancel order if maker does not meet balance threshold', async () => {
- // Create orders to cancel
- const invalidSignedOrders = [
- await invalidOrderFactory.newSignedOrderAsync(),
- await invalidOrderFactory.newSignedOrderAsync(),
- await invalidOrderFactory.newSignedOrderAsync(),
- ];
- // Verify orders are not cancelled
- _.each(invalidSignedOrders, async signedOrder => {
- const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- });
- // Cancel
- const txReceipt = await erc721NonValidBalanceThresholdWrapper.batchCancelOrdersAsync(
- invalidSignedOrders,
- invalidAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- _.each(invalidSignedOrders, async signedOrder => {
- const orderInfoAfterCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- });
- });
- });
-
- describe('cancelOrdersUpTo', () => {
- beforeEach(async () => {
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- });
- it('Should successfully batch cancel orders if maker meets balance threshold', async () => {
- // Create orders to cancel
- const validSignedOrders = [
- await orderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }),
- await orderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }),
- await orderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }),
- ];
- // Verify orders are not cancelled
- _.each(validSignedOrders, async signedOrder => {
- const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- });
- // Cancel
- const cancelOrdersUpToThisSalt = new BigNumber(1);
- const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync(
- cancelOrdersUpToThisSalt,
- validSignedOrders[0].makerAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- _.each(validSignedOrders, async (signedOrder, salt: number) => {
- const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- const saltAsBigNumber = new BigNumber(salt);
- if (saltAsBigNumber.isLessThanOrEqualTo(cancelOrdersUpToThisSalt)) {
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- } else {
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- }
- });
- });
- it('Should successfully batch cancel order if maker does not meet balance threshold', async () => {
- // Create orders to cancel
- const invalidSignedOrders = [
- await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }),
- await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }),
- await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }),
- ];
- // Verify orders are not cancelled
- _.each(invalidSignedOrders, async signedOrder => {
- const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- });
- // Cancel
- const cancelOrdersUpToThisSalt = new BigNumber(1);
- const txReceipt = await erc721NonValidBalanceThresholdWrapper.cancelOrdersUpToAsync(
- cancelOrdersUpToThisSalt,
- invalidAddress,
- );
- // Assert validated addresses
- const expectedValidatedAddresseses: string[] = [];
- await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
- // Check that order was cancelled
- _.each(invalidSignedOrders, async (signedOrder, salt: number) => {
- const orderInfoAfterCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync(
- signedOrder,
- );
- const saltAsBigNumber = new BigNumber(salt);
- if (saltAsBigNumber.isLessThanOrEqualTo(cancelOrdersUpToThisSalt)) {
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Cancelled);
- } else {
- return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.Fillable);
- }
- });
- });
- });
-});
-// tslint:disable:max-file-line-count
-// tslint:enable:no-unnecessary-type-assertion
diff --git a/contracts/extensions/test/extensions/dutch_auction.ts b/contracts/extensions/test/extensions/dutch_auction.ts
deleted file mode 100644
index 22b3caa16..000000000
--- a/contracts/extensions/test/extensions/dutch_auction.ts
+++ /dev/null
@@ -1,378 +0,0 @@
-import { DutchAuctionWrapper } from '@0x/contract-wrappers';
-import {
- artifacts as protocolArtifacts,
- ERC20Wrapper,
- ERC721Wrapper,
- ExchangeContract,
- ExchangeWrapper,
-} from '@0x/contracts-protocol';
-import {
- chaiSetup,
- constants,
- ContractName,
- ERC20BalancesByOwner,
- expectTransactionFailedAsync,
- getLatestBlockTimestampAsync,
- OrderFactory,
- provider,
- txDefaults,
- web3Wrapper,
-} from '@0x/contracts-test-utils';
-import {
- artifacts as tokensArtifacts,
- DummyERC20TokenContract,
- DummyERC721TokenContract,
- WETH9Contract,
-} from '@0x/contracts-tokens';
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
-import { RevertReason, SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-
-import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
-import { artifacts } from '../../src/artifacts';
-import { DutchAuctionTestWrapper } from '../utils/dutch_auction_test_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-const DECIMALS_DEFAULT = 18;
-
-describe(ContractName.DutchAuction, () => {
- let makerAddress: string;
- let owner: string;
- let takerAddress: string;
- let feeRecipientAddress: string;
- let defaultMakerAssetAddress: string;
-
- let zrxToken: DummyERC20TokenContract;
- let erc20TokenA: DummyERC20TokenContract;
- let erc721Token: DummyERC721TokenContract;
- let dutchAuctionContract: DutchAuctionContract;
- let wethContract: WETH9Contract;
-
- let sellerOrderFactory: OrderFactory;
- let buyerOrderFactory: OrderFactory;
- let erc20Wrapper: ERC20Wrapper;
- let erc20Balances: ERC20BalancesByOwner;
- let currentBlockTimestamp: number;
- let auctionBeginTimeSeconds: BigNumber;
- let auctionEndTimeSeconds: BigNumber;
- let auctionBeginAmount: BigNumber;
- let auctionEndAmount: BigNumber;
- let sellOrder: SignedOrder;
- let buyOrder: SignedOrder;
- let erc721MakerAssetIds: BigNumber[];
- const tenMinutesInSeconds = 10 * 60;
-
- let dutchAuctionTestWrapper: DutchAuctionTestWrapper;
- let defaultERC20MakerAssetData: string;
-
- before(async () => {
- await blockchainLifecycle.startAsync();
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
-
- erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
-
- const numDummyErc20ToDeploy = 2;
- [erc20TokenA, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
- numDummyErc20ToDeploy,
- constants.DUMMY_TOKEN_DECIMALS,
- );
- const erc20Proxy = await erc20Wrapper.deployProxyAsync();
- await erc20Wrapper.setBalancesAndAllowancesAsync();
-
- const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
- const erc721Proxy = await erc721Wrapper.deployProxyAsync();
- await erc721Wrapper.setBalancesAndAllowancesAsync();
- const erc721Balances = await erc721Wrapper.getBalancesAsync();
- erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
-
- wethContract = await WETH9Contract.deployFrom0xArtifactAsync(tokensArtifacts.WETH9, provider, txDefaults);
- erc20Wrapper.addDummyTokenContract(wethContract as any);
-
- const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- zrxAssetData,
- );
- const exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
- await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
-
- await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
- from: owner,
- });
- await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
- from: owner,
- });
-
- const dutchAuctionInstance = await DutchAuctionContract.deployFrom0xArtifactAsync(
- artifacts.DutchAuction,
- provider,
- txDefaults,
- exchangeInstance.address,
- );
- dutchAuctionContract = new DutchAuctionContract(
- dutchAuctionInstance.abi,
- dutchAuctionInstance.address,
- provider,
- );
- dutchAuctionTestWrapper = new DutchAuctionTestWrapper(dutchAuctionInstance, provider);
-
- defaultMakerAssetAddress = erc20TokenA.address;
- const defaultTakerAssetAddress = wethContract.address;
-
- // Set up taker WETH balance and allowance
- await web3Wrapper.awaitTransactionSuccessAsync(
- await wethContract.deposit.sendTransactionAsync({
- from: takerAddress,
- value: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
- }),
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await wethContract.approve.sendTransactionAsync(
- erc20Proxy.address,
- constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
- { from: takerAddress },
- ),
- );
- web3Wrapper.abiDecoder.addABI(exchangeInstance.abi);
- web3Wrapper.abiDecoder.addABI(zrxToken.abi);
- erc20Wrapper.addTokenOwnerAddress(dutchAuctionContract.address);
-
- currentBlockTimestamp = await getLatestBlockTimestampAsync();
- // Default auction begins 10 minutes ago
- auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp).minus(tenMinutesInSeconds);
- // Default auction ends 10 from now
- auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds);
- auctionBeginAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT);
- auctionEndAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT);
-
- // Default sell order and buy order are exact mirrors
- const sellerDefaultOrderParams = {
- salt: generatePseudoRandomSalt(),
- exchangeAddress: exchangeInstance.address,
- makerAddress,
- feeRecipientAddress,
- // taker address or sender address should be set to the ducth auction contract
- takerAddress: dutchAuctionContract.address,
- makerAssetData: DutchAuctionWrapper.encodeDutchAuctionAssetData(
- assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- ),
- takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
- takerAssetAmount: auctionEndAmount,
- expirationTimeSeconds: auctionEndTimeSeconds,
- makerFee: constants.ZERO_AMOUNT,
- takerFee: constants.ZERO_AMOUNT,
- };
- // Default buy order is for the auction begin price
- const buyerDefaultOrderParams = {
- ...sellerDefaultOrderParams,
- makerAddress: takerAddress,
- makerAssetData: sellerDefaultOrderParams.takerAssetData,
- takerAssetData: sellerDefaultOrderParams.makerAssetData,
- makerAssetAmount: auctionBeginAmount,
- takerAssetAmount: sellerDefaultOrderParams.makerAssetAmount,
- };
- const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
- const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
- sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
- buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
- defaultERC20MakerAssetData = assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress);
- });
- after(async () => {
- await blockchainLifecycle.revertAsync();
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- sellOrder = await sellerOrderFactory.newSignedOrderAsync();
- buyOrder = await buyerOrderFactory.newSignedOrderAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('matchOrders', () => {
- it('should be worth the begin price at the begining of the auction', async () => {
- auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2);
- const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
- defaultERC20MakerAssetData,
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- );
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({ makerAssetData });
- const auctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- expect(auctionDetails.currentTimeSeconds).to.be.bignumber.lte(auctionBeginTimeSeconds);
- expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount);
- expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
- });
- it('should be be worth the end price at the end of the auction', async () => {
- auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
- auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
- const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
- defaultERC20MakerAssetData,
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- );
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- makerAssetData,
- expirationTimeSeconds: auctionEndTimeSeconds,
- });
- const auctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- expect(auctionDetails.currentTimeSeconds).to.be.bignumber.gte(auctionEndTimeSeconds);
- expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount);
- expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
- });
- it('should match orders at current amount and send excess to buyer', async () => {
- const beforeAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- buyOrder = await buyerOrderFactory.newSignedOrderAsync({
- makerAssetAmount: beforeAuctionDetails.currentAmount.times(2),
- });
- await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
- const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- // HACK gte used here due to a bug in ganache where the timestamp can change
- // between multiple calls to the same block. Which can move the amount in our case
- // ref: https://github.com/trufflesuite/ganache-core/issues/111
- expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
- erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
- );
- expect(newBalances[takerAddress][wethContract.address]).to.be.bignumber.gte(
- erc20Balances[takerAddress][wethContract.address].minus(beforeAuctionDetails.currentAmount),
- );
- });
- it('maker fees on sellOrder are paid to the fee receipient', async () => {
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- makerFee: new BigNumber(1),
- });
- await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
- const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
- erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(sellOrder.makerFee),
- );
- });
- it('maker fees on buyOrder are paid to the fee receipient', async () => {
- buyOrder = await buyerOrderFactory.newSignedOrderAsync({
- makerFee: new BigNumber(1),
- });
- await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
- erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
- );
- expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[feeRecipientAddress][zrxToken.address].plus(buyOrder.makerFee),
- );
- });
- it('should revert when auction expires', async () => {
- auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
- auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
- const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
- defaultERC20MakerAssetData,
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- );
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- expirationTimeSeconds: auctionEndTimeSeconds,
- makerAssetData,
- });
- return expectTransactionFailedAsync(
- dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
- RevertReason.AuctionExpired,
- );
- });
- it('cannot be filled for less than the current price', async () => {
- buyOrder = await buyerOrderFactory.newSignedOrderAsync({
- makerAssetAmount: sellOrder.takerAssetAmount,
- });
- return expectTransactionFailedAsync(
- dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
- RevertReason.AuctionInvalidAmount,
- );
- });
- it('auction begin amount must be higher than final amount ', async () => {
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- takerAssetAmount: auctionBeginAmount.plus(1),
- });
- return expectTransactionFailedAsync(
- dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
- RevertReason.AuctionInvalidAmount,
- );
- });
- it('begin time is less than end time', async () => {
- auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds);
- const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
- defaultERC20MakerAssetData,
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- );
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- expirationTimeSeconds: auctionEndTimeSeconds,
- makerAssetData,
- });
- return expectTransactionFailedAsync(
- dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
- RevertReason.AuctionInvalidBeginTime,
- );
- });
- it('asset data contains auction parameters', async () => {
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- });
- return expectTransactionFailedAsync(
- dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
- RevertReason.InvalidAssetData,
- );
- });
-
- describe('ERC721', () => {
- it('should match orders when ERC721', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- const erc721MakerAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId);
- const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
- erc721MakerAssetData,
- auctionBeginTimeSeconds,
- auctionBeginAmount,
- );
- sellOrder = await sellerOrderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData,
- });
- buyOrder = await buyerOrderFactory.newSignedOrderAsync({
- takerAssetAmount: new BigNumber(1),
- takerAssetData: sellOrder.makerAssetData,
- });
- await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
- const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- // HACK gte used here due to a bug in ganache where the timestamp can change
- // between multiple calls to the same block. Which can move the amount in our case
- // ref: https://github.com/trufflesuite/ganache-core/issues/111
- expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
- erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
- );
- const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
- expect(newOwner).to.be.bignumber.equal(takerAddress);
- });
- });
- });
-});
diff --git a/contracts/extensions/test/extensions/forwarder.ts b/contracts/extensions/test/extensions/forwarder.ts
deleted file mode 100644
index 69939ed04..000000000
--- a/contracts/extensions/test/extensions/forwarder.ts
+++ /dev/null
@@ -1,1291 +0,0 @@
-import {
- artifacts as protocolArtifacts,
- ERC20Wrapper,
- ERC721Wrapper,
- ExchangeContract,
- ExchangeWrapper,
-} from '@0x/contracts-protocol';
-import {
- chaiSetup,
- constants,
- ContractName,
- ERC20BalancesByOwner,
- expectContractCreationFailedAsync,
- expectTransactionFailedAsync,
- OrderFactory,
- provider,
- sendTransactionResult,
- txDefaults,
- web3Wrapper,
-} from '@0x/contracts-test-utils';
-import {
- artifacts as tokenArtifacts,
- DummyERC20TokenContract,
- DummyERC721TokenContract,
- WETH9Contract,
-} from '@0x/contracts-tokens';
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { assetDataUtils } from '@0x/order-utils';
-import { RevertReason, SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import * as chai from 'chai';
-import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-
-import { ForwarderContract } from '../../generated-wrappers/forwarder';
-import { artifacts } from '../../src/artifacts';
-
-import { ForwarderWrapper } from '../utils/forwarder_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-const DECIMALS_DEFAULT = 18;
-const MAX_WETH_FILL_PERCENTAGE = 95;
-
-describe(ContractName.Forwarder, () => {
- let makerAddress: string;
- let owner: string;
- let takerAddress: string;
- let feeRecipientAddress: string;
- let defaultMakerAssetAddress: string;
- let zrxAssetData: string;
- let wethAssetData: string;
-
- let weth: DummyERC20TokenContract;
- let zrxToken: DummyERC20TokenContract;
- let erc20TokenA: DummyERC20TokenContract;
- let erc721Token: DummyERC721TokenContract;
- let forwarderContract: ForwarderContract;
- let wethContract: WETH9Contract;
- let forwarderWrapper: ForwarderWrapper;
- let exchangeWrapper: ExchangeWrapper;
-
- let orderWithoutFee: SignedOrder;
- let orderWithFee: SignedOrder;
- let feeOrder: SignedOrder;
- let orderFactory: OrderFactory;
- let erc20Wrapper: ERC20Wrapper;
- let erc20Balances: ERC20BalancesByOwner;
- let tx: TransactionReceiptWithDecodedLogs;
-
- let erc721MakerAssetIds: BigNumber[];
- let takerEthBalanceBefore: BigNumber;
- let feePercentage: BigNumber;
- let gasPrice: BigNumber;
-
- before(async () => {
- await blockchainLifecycle.startAsync();
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts);
-
- const txHash = await web3Wrapper.sendTransactionAsync({ from: accounts[0], to: accounts[0], value: 0 });
- const transaction = await web3Wrapper.getTransactionByHashAsync(txHash);
- gasPrice = new BigNumber(transaction.gasPrice);
-
- const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
-
- const numDummyErc20ToDeploy = 3;
- [erc20TokenA, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
- numDummyErc20ToDeploy,
- constants.DUMMY_TOKEN_DECIMALS,
- );
- const erc20Proxy = await erc20Wrapper.deployProxyAsync();
- await erc20Wrapper.setBalancesAndAllowancesAsync();
-
- [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
- const erc721Proxy = await erc721Wrapper.deployProxyAsync();
- await erc721Wrapper.setBalancesAndAllowancesAsync();
- const erc721Balances = await erc721Wrapper.getBalancesAsync();
- erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
-
- wethContract = await WETH9Contract.deployFrom0xArtifactAsync(tokenArtifacts.WETH9, provider, txDefaults);
- weth = new DummyERC20TokenContract(wethContract.abi, wethContract.address, provider);
- erc20Wrapper.addDummyTokenContract(weth);
-
- wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
- zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- zrxAssetData,
- );
- exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
- await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
-
- await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
- from: owner,
- });
- await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, {
- from: owner,
- });
-
- defaultMakerAssetAddress = erc20TokenA.address;
- const defaultTakerAssetAddress = wethContract.address;
- const defaultOrderParams = {
- exchangeAddress: exchangeInstance.address,
- makerAddress,
- feeRecipientAddress,
- makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
- takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
- makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
- };
- const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
- orderFactory = new OrderFactory(privateKey, defaultOrderParams);
-
- const forwarderInstance = await ForwarderContract.deployFrom0xArtifactAsync(
- artifacts.Forwarder,
- provider,
- txDefaults,
- exchangeInstance.address,
- zrxAssetData,
- wethAssetData,
- );
- forwarderContract = new ForwarderContract(forwarderInstance.abi, forwarderInstance.address, provider);
- forwarderWrapper = new ForwarderWrapper(forwarderContract, provider);
- const zrxDepositAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.transfer.sendTransactionAsync(forwarderContract.address, zrxDepositAmount),
- );
- erc20Wrapper.addTokenOwnerAddress(forwarderInstance.address);
- });
- after(async () => {
- await blockchainLifecycle.revertAsync();
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- erc20Balances = await erc20Wrapper.getBalancesAsync();
- takerEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- orderWithoutFee = await orderFactory.newSignedOrderAsync();
- feeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- orderWithFee = await orderFactory.newSignedOrderAsync({
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
- describe('constructor', () => {
- it('should revert if assetProxy is unregistered', async () => {
- const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- zrxAssetData,
- );
- return expectContractCreationFailedAsync(
- (ForwarderContract.deployFrom0xArtifactAsync(
- artifacts.Forwarder,
- provider,
- txDefaults,
- exchangeInstance.address,
- zrxAssetData,
- wethAssetData,
- ) as any) as sendTransactionResult,
- RevertReason.UnregisteredAssetProxy,
- );
- });
- });
- describe('marketSellOrdersWithEth without extra fees', () => {
- it('should fill a single order', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
- ethValue,
- MAX_WETH_FILL_PERCENTAGE,
- );
- const makerAssetFillAmount = primaryTakerAssetFillAmount
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fill multiple orders', async () => {
- const secondOrderWithoutFee = await orderFactory.newSignedOrderAsync();
- const ordersWithoutFee = [orderWithoutFee, secondOrderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const ethValue = ordersWithoutFee[0].takerAssetAmount.plus(
- ordersWithoutFee[1].takerAssetAmount.dividedToIntegerBy(2),
- );
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
- ethValue,
- MAX_WETH_FILL_PERCENTAGE,
- );
- const firstTakerAssetFillAmount = ordersWithoutFee[0].takerAssetAmount;
- const secondTakerAssetFillAmount = primaryTakerAssetFillAmount.minus(firstTakerAssetFillAmount);
-
- const makerAssetFillAmount = ordersWithoutFee[0].makerAssetAmount.plus(
- ordersWithoutFee[1].makerAssetAmount
- .times(secondTakerAssetFillAmount)
- .dividedToIntegerBy(ordersWithoutFee[1].takerAssetAmount),
- );
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fill the order and pay ZRX fees from a single feeOrder', async () => {
- const ordersWithFee = [orderWithFee];
- const feeOrders = [feeOrder];
- const ethValue = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
- ethValue,
- MAX_WETH_FILL_PERCENTAGE,
- );
- const makerAssetFillAmount = primaryTakerAssetFillAmount
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- const feeAmount = ForwarderWrapper.getPercentageOfValue(
- orderWithFee.takerFee.dividedToIntegerBy(2),
- MAX_WETH_FILL_PERCENTAGE,
- );
- const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
- const totalEthSpent = primaryTakerAssetFillAmount
- .plus(wethSpentOnFeeOrders)
- .plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fill the orders and pay ZRX from multiple feeOrders', async () => {
- const ordersWithFee = [orderWithFee];
- const ethValue = orderWithFee.takerAssetAmount;
- const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- const makerAssetAmount = orderWithFee.takerFee.dividedToIntegerBy(2);
- const takerAssetAmount = feeOrder.takerAssetAmount
- .times(makerAssetAmount)
- .dividedToIntegerBy(feeOrder.makerAssetAmount);
-
- const firstFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData,
- makerAssetAmount,
- takerAssetAmount,
- });
- const secondFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData,
- makerAssetAmount,
- takerAssetAmount,
- });
- const feeOrders = [firstFeeOrder, secondFeeOrder];
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
- ethValue,
- MAX_WETH_FILL_PERCENTAGE,
- );
- const makerAssetFillAmount = primaryTakerAssetFillAmount
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- const feeAmount = ForwarderWrapper.getPercentageOfValue(orderWithFee.takerFee, MAX_WETH_FILL_PERCENTAGE);
- const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
- const totalEthSpent = primaryTakerAssetFillAmount
- .plus(wethSpentOnFeeOrders)
- .plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fill the order when token is ZRX with fees', async () => {
- orderWithFee = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- const ordersWithFee = [orderWithFee];
- const feeOrders: SignedOrder[] = [];
- const ethValue = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
- const totalEthSpent = ethValue.plus(gasPrice.times(tx.gasUsed));
- const takerFeePaid = orderWithFee.takerFee.dividedToIntegerBy(2);
- const makerFeePaid = orderWithFee.makerFee.dividedToIntegerBy(2);
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFillAmount).minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFillAmount).minus(takerFeePaid),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(ethValue),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[forwarderContract.address][zrxToken.address],
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should refund remaining ETH if amount is greater than takerAssetAmount', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const ethValue = orderWithoutFee.takerAssetAmount.times(2);
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const totalEthSpent = orderWithoutFee.takerAssetAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- });
- it('should revert if ZRX cannot be fully repurchased', async () => {
- orderWithFee = await orderFactory.newSignedOrderAsync({
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
- });
- const ordersWithFee = [orderWithFee];
- feeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- const feeOrders = [feeOrder];
- const ethValue = orderWithFee.takerAssetAmount;
- return expectTransactionFailedAsync(
- forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- }),
- RevertReason.CompleteFillFailed,
- );
- });
- it('should not fill orders with different makerAssetData than the first order', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
- const ordersWithoutFee = [erc20SignedOrder, erc721SignedOrder];
- const feeOrders: SignedOrder[] = [];
- const ethValue = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
-
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(ordersWithoutFee, feeOrders, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const totalEthSpent = erc20SignedOrder.takerAssetAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- });
- });
- describe('marketSellOrdersWithEth with extra fees', () => {
- it('should fill the order and send fee to feeRecipient', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const ethValue = orderWithoutFee.takerAssetAmount.div(2);
-
- const baseFeePercentage = 2;
- feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
- const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- tx = await forwarderWrapper.marketSellOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- {
- value: ethValue,
- from: takerAddress,
- },
- { feePercentage, feeRecipient: feeRecipientAddress },
- );
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getPercentageOfValue(
- ethValue,
- MAX_WETH_FILL_PERCENTAGE,
- );
- const makerAssetFillAmount = primaryTakerAssetFillAmount
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- const ethSpentOnFee = ForwarderWrapper.getPercentageOfValue(primaryTakerAssetFillAmount, baseFeePercentage);
- const totalEthSpent = primaryTakerAssetFillAmount.plus(ethSpentOnFee).plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(feeRecipientEthBalanceAfter).to.be.bignumber.equal(feeRecipientEthBalanceBefore.plus(ethSpentOnFee));
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fail if the fee is set too high', async () => {
- const ethValue = orderWithoutFee.takerAssetAmount.div(2);
- const baseFeePercentage = 6;
- feePercentage = ForwarderWrapper.getPercentageOfValue(ethValue, baseFeePercentage);
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- await expectTransactionFailedAsync(
- forwarderWrapper.marketSellOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- { from: takerAddress, value: ethValue, gasPrice },
- { feePercentage, feeRecipient: feeRecipientAddress },
- ),
- RevertReason.FeePercentageTooLarge,
- );
- });
- it('should fail if there is not enough ETH remaining to pay the fee', async () => {
- const ethValue = orderWithoutFee.takerAssetAmount.div(2);
- const baseFeePercentage = 5;
- feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
- const ordersWithFee = [orderWithFee];
- const feeOrders = [feeOrder];
- await expectTransactionFailedAsync(
- forwarderWrapper.marketSellOrdersWithEthAsync(
- ordersWithFee,
- feeOrders,
- { from: takerAddress, value: ethValue, gasPrice },
- { feePercentage, feeRecipient: feeRecipientAddress },
- ),
- RevertReason.InsufficientEthRemaining,
- );
- });
- });
- describe('marketBuyOrdersWithEth without extra fees', () => {
- it('should buy the exact amount of makerAsset in a single order', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should buy the exact amount of makerAsset in multiple orders', async () => {
- const secondOrderWithoutFee = await orderFactory.newSignedOrderAsync();
- const ordersWithoutFee = [orderWithoutFee, secondOrderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = ordersWithoutFee[0].makerAssetAmount.plus(
- ordersWithoutFee[1].makerAssetAmount.dividedToIntegerBy(2),
- );
- const ethValue = ordersWithoutFee[0].takerAssetAmount.plus(
- ordersWithoutFee[1].takerAssetAmount.dividedToIntegerBy(2),
- );
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should buy the exact amount of makerAsset and return excess ETH', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount;
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ethValue.dividedToIntegerBy(2);
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should buy the exact amount of makerAsset and pay ZRX from feeOrders', async () => {
- const ordersWithFee = [orderWithFee];
- const feeOrders = [feeOrder];
- const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithFee.takerAssetAmount;
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = orderWithFee.takerAssetAmount.dividedToIntegerBy(2);
- const feeAmount = orderWithFee.takerFee.dividedToIntegerBy(2);
- const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
- const totalEthSpent = primaryTakerAssetFillAmount
- .plus(wethSpentOnFeeOrders)
- .plus(gasPrice.times(tx.gasUsed));
-
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should buy slightly greater than makerAssetAmount when buying ZRX', async () => {
- orderWithFee = await orderFactory.newSignedOrderAsync({
- makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- const ordersWithFee = [orderWithFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithFee.takerAssetAmount;
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ForwarderWrapper.getWethForFeeOrders(
- makerAssetFillAmount,
- ordersWithFee,
- );
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- const makerAssetFilledAmount = orderWithFee.makerAssetAmount
- .times(primaryTakerAssetFillAmount)
- .dividedToIntegerBy(orderWithFee.takerAssetAmount);
- const takerFeePaid = orderWithFee.takerFee
- .times(primaryTakerAssetFillAmount)
- .dividedToIntegerBy(orderWithFee.takerAssetAmount);
- const makerFeePaid = orderWithFee.makerFee
- .times(primaryTakerAssetFillAmount)
- .dividedToIntegerBy(orderWithFee.takerAssetAmount);
- const totalZrxPurchased = makerAssetFilledAmount.minus(takerFeePaid);
- // Up to 1 wei worth of ZRX will be overbought per order
- const maxOverboughtZrx = new BigNumber(1)
- .times(orderWithFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithFee.takerAssetAmount);
-
- expect(totalZrxPurchased).to.be.bignumber.gte(makerAssetFillAmount);
- expect(totalZrxPurchased).to.be.bignumber.lte(makerAssetFillAmount.plus(maxOverboughtZrx));
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFilledAmount).minus(makerFeePaid),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].plus(totalZrxPurchased),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[forwarderContract.address][zrxToken.address],
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should revert if the amount of ETH sent is too low to fill the makerAssetAmount', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(4);
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- }),
- RevertReason.CompleteFillFailed,
- );
- });
- it('should buy an ERC721 asset from a single order', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = new BigNumber(1);
- const ethValue = orderWithFee.takerAssetAmount;
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- from: takerAddress,
- value: ethValue,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- expect(newOwner).to.be.bignumber.equal(takerAddress);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should revert if buying an ERC721 asset when later orders contain different makerAssetData', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- });
- const differentMakerAssetDataOrder = await orderFactory.newSignedOrderAsync();
- const ordersWithoutFee = [orderWithoutFee, differentMakerAssetDataOrder];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = new BigNumber(1).plus(differentMakerAssetDataOrder.makerAssetAmount);
- const ethValue = orderWithFee.takerAssetAmount;
- return expectTransactionFailedAsync(
- forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- }),
- RevertReason.CompleteFillFailed,
- );
- });
- it('should buy an ERC721 asset and pay ZRX fees from a single fee order', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- orderWithFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- const ordersWithFee = [orderWithFee];
- const feeOrders = [feeOrder];
- const makerAssetFillAmount = orderWithFee.makerAssetAmount;
- const primaryTakerAssetFillAmount = orderWithFee.takerAssetAmount;
- const feeAmount = orderWithFee.takerFee;
- const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
- const ethValue = primaryTakerAssetFillAmount.plus(wethSpentOnFeeOrders);
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const totalEthSpent = ethValue.plus(gasPrice.times(tx.gasUsed));
-
- expect(newOwner).to.be.bignumber.equal(takerAddress);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should buy an ERC721 asset and pay ZRX fees from multiple fee orders', async () => {
- const makerAssetId = erc721MakerAssetIds[0];
- orderWithFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber(1),
- makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
- takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
- });
- const ordersWithFee = [orderWithFee];
- const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- const makerAssetAmount = orderWithFee.takerFee.dividedToIntegerBy(2);
- const takerAssetAmount = feeOrder.takerAssetAmount
- .times(makerAssetAmount)
- .dividedToIntegerBy(feeOrder.makerAssetAmount);
-
- const firstFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData,
- makerAssetAmount,
- takerAssetAmount,
- });
- const secondFeeOrder = await orderFactory.newSignedOrderAsync({
- makerAssetData,
- makerAssetAmount,
- takerAssetAmount,
- });
- const feeOrders = [firstFeeOrder, secondFeeOrder];
-
- const makerAssetFillAmount = orderWithFee.makerAssetAmount;
- const primaryTakerAssetFillAmount = orderWithFee.takerAssetAmount;
- const feeAmount = orderWithFee.takerFee;
- const wethSpentOnFeeOrders = ForwarderWrapper.getWethForFeeOrders(feeAmount, feeOrders);
- const ethValue = primaryTakerAssetFillAmount.plus(wethSpentOnFeeOrders);
-
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newOwner = await erc721Token.ownerOf.callAsync(makerAssetId);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const totalEthSpent = ethValue.plus(gasPrice.times(tx.gasUsed));
-
- expect(newOwner).to.be.bignumber.equal(takerAddress);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount).plus(wethSpentOnFeeOrders),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('Should buy slightly greater MakerAsset when exchange rate is rounded', async () => {
- // The 0x Protocol contracts round the exchange rate in favor of the Maker.
- // In this case, the taker must round up how much they're going to spend, which
- // in turn increases the amount of MakerAsset being purchased.
- // Example:
- // The taker wants to buy 5 units of the MakerAsset at a rate of 3M/2T.
- // For every 2 units of TakerAsset, the taker will receive 3 units of MakerAsset.
- // To purchase 5 units, the taker must spend 10/3 = 3.33 units of TakerAssset.
- // However, the Taker can only spend whole units.
- // Spending floor(10/3) = 3 units will yield a profit of Floor(3*3/2) = Floor(4.5) = 4 units of MakerAsset.
- // Spending ceil(10/3) = 4 units will yield a profit of Floor(4*3/2) = 6 units of MakerAsset.
- //
- // The forwarding contract will opt for the second option, which overbuys, to ensure the taker
- // receives at least the amount of MakerAsset they requested.
- //
- // Construct test case using values from example above
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber('30'),
- takerAssetAmount: new BigNumber('20'),
- makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
- takerAssetData: assetDataUtils.encodeERC20AssetData(weth.address),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const desiredMakerAssetFillAmount = new BigNumber('5');
- const makerAssetFillAmount = new BigNumber('6');
- const ethValue = new BigNumber('4');
- // Execute test case
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- desiredMakerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- );
- // Fetch end balances and construct expected outputs
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- // Validate test case
- expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('Should buy slightly greater MakerAsset when exchange rate is rounded, and MakerAsset is ZRX', async () => {
- // See the test case above for a detailed description of this case.
- // The difference here is that the MakerAsset is ZRX. We expect the same result as above,
- // but this tests a different code path.
- //
- // Construct test case using values from example above
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber('30'),
- takerAssetAmount: new BigNumber('20'),
- makerAssetData: zrxAssetData,
- takerAssetData: assetDataUtils.encodeERC20AssetData(weth.address),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const desiredMakerAssetFillAmount = new BigNumber('5');
- const makerAssetFillAmount = new BigNumber('6');
- const ethValue = new BigNumber('4');
- // Execute test case
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- desiredMakerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- );
- // Fetch end balances and construct expected outputs
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- // Validate test case
- expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('Should buy slightly greater MakerAsset when exchange rate is rounded (Regression Test)', async () => {
- // Order taken from a transaction on mainnet that failed due to a rounding error.
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber('268166666666666666666'),
- takerAssetAmount: new BigNumber('219090625878836371'),
- makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
- takerAssetData: assetDataUtils.encodeERC20AssetData(weth.address),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- // The taker will receive more than the desired amount of makerAsset due to rounding
- const desiredMakerAssetFillAmount = new BigNumber('5000000000000000000');
- const ethValue = new BigNumber('4084971271824171');
- const makerAssetFillAmount = ethValue
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- // Execute test case
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- desiredMakerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- );
- // Fetch end balances and construct expected outputs
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- // Validate test case
- expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('Should buy slightly greater MakerAsset when exchange rate is rounded, and MakerAsset is ZRX (Regression Test)', async () => {
- // Order taken from a transaction on mainnet that failed due to a rounding error.
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber('268166666666666666666'),
- takerAssetAmount: new BigNumber('219090625878836371'),
- makerAssetData: zrxAssetData,
- takerAssetData: assetDataUtils.encodeERC20AssetData(weth.address),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- // The taker will receive more than the desired amount of makerAsset due to rounding
- const desiredMakerAssetFillAmount = new BigNumber('5000000000000000000');
- const ethValue = new BigNumber('4084971271824171');
- const makerAssetFillAmount = ethValue
- .times(orderWithoutFee.makerAssetAmount)
- .dividedToIntegerBy(orderWithoutFee.takerAssetAmount);
- // Execute test case
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- desiredMakerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- );
- // Fetch end balances and construct expected outputs
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- // Validate test case
- expect(makerAssetFillAmount).to.be.bignumber.greaterThan(desiredMakerAssetFillAmount);
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('Should buy correct MakerAsset when exchange rate is NOT rounded, and MakerAsset is ZRX (Regression Test)', async () => {
- // An extra unit of TakerAsset was sent to the exchange contract to account for rounding errors, in Forwarder v1.
- // Specifically, the takerFillAmount was calculated using Floor(desiredMakerAmount * exchangeRate) + 1
- // We have since changed this to be Ceil(desiredMakerAmount * exchangeRate)
- // These calculations produce different results when `desiredMakerAmount * exchangeRate` is an integer.
- //
- // This test verifies that `ceil` is sufficient:
- // Let TakerAssetAmount = MakerAssetAmount * 2
- // -> exchangeRate = TakerAssetAmount / MakerAssetAmount = (2*MakerAssetAmount)/MakerAssetAmount = 2
- // .: desiredMakerAmount * exchangeRate is an integer.
- //
- // Construct test case using values from example above
- orderWithoutFee = await orderFactory.newSignedOrderAsync({
- makerAssetAmount: new BigNumber('30'),
- takerAssetAmount: new BigNumber('60'),
- makerAssetData: zrxAssetData,
- takerAssetData: assetDataUtils.encodeERC20AssetData(weth.address),
- makerFee: new BigNumber(0),
- takerFee: new BigNumber(0),
- });
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = new BigNumber('5');
- const ethValue = new BigNumber('10');
- // Execute test case
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(ordersWithoutFee, feeOrders, makerAssetFillAmount, {
- value: ethValue,
- from: takerAddress,
- });
- // Fetch end balances and construct expected outputs
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const newBalances = await erc20Wrapper.getBalancesAsync();
- const primaryTakerAssetFillAmount = ethValue;
- const totalEthSpent = primaryTakerAssetFillAmount.plus(gasPrice.times(tx.gasUsed));
- // Validate test case
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- });
- describe('marketBuyOrdersWithEth with extra fees', () => {
- it('should buy an asset and send fee to feeRecipient', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount;
-
- const baseFeePercentage = 2;
- feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
- const feeRecipientEthBalanceBefore = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- tx = await forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- makerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- { feePercentage, feeRecipient: feeRecipientAddress },
- );
- const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(takerAddress);
- const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(forwarderContract.address);
- const feeRecipientEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(feeRecipientAddress);
- const newBalances = await erc20Wrapper.getBalancesAsync();
-
- const primaryTakerAssetFillAmount = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
- const ethSpentOnFee = ForwarderWrapper.getPercentageOfValue(primaryTakerAssetFillAmount, baseFeePercentage);
- const totalEthSpent = primaryTakerAssetFillAmount.plus(ethSpentOnFee).plus(gasPrice.times(tx.gasUsed));
-
- expect(feeRecipientEthBalanceAfter).to.be.bignumber.equal(feeRecipientEthBalanceBefore.plus(ethSpentOnFee));
- expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
- expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
- );
- expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
- erc20Balances[takerAddress][defaultMakerAssetAddress].plus(makerAssetFillAmount),
- );
- expect(newBalances[makerAddress][weth.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][weth.address].plus(primaryTakerAssetFillAmount),
- );
- expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(newBalances[forwarderContract.address][defaultMakerAssetAddress]).to.be.bignumber.equal(
- constants.ZERO_AMOUNT,
- );
- expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should fail if the fee is set too high', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount;
-
- const baseFeePercentage = 6;
- feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
- await expectTransactionFailedAsync(
- forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- makerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- { feePercentage, feeRecipient: feeRecipientAddress },
- ),
- RevertReason.FeePercentageTooLarge,
- );
- });
- it('should fail if there is not enough ETH remaining to pay the fee', async () => {
- const ordersWithoutFee = [orderWithoutFee];
- const feeOrders: SignedOrder[] = [];
- const makerAssetFillAmount = orderWithoutFee.makerAssetAmount.dividedToIntegerBy(2);
- const ethValue = orderWithoutFee.takerAssetAmount.dividedToIntegerBy(2);
-
- const baseFeePercentage = 2;
- feePercentage = ForwarderWrapper.getPercentageOfValue(constants.PERCENTAGE_DENOMINATOR, baseFeePercentage);
- await expectTransactionFailedAsync(
- forwarderWrapper.marketBuyOrdersWithEthAsync(
- ordersWithoutFee,
- feeOrders,
- makerAssetFillAmount,
- {
- value: ethValue,
- from: takerAddress,
- },
- { feePercentage, feeRecipient: feeRecipientAddress },
- ),
- RevertReason.InsufficientEthRemaining,
- );
- });
- });
- describe('withdrawAsset', () => {
- it('should allow owner to withdraw ERC20 tokens', async () => {
- const zrxWithdrawAmount = erc20Balances[forwarderContract.address][zrxToken.address];
- await forwarderWrapper.withdrawAssetAsync(zrxAssetData, zrxWithdrawAmount, { from: owner });
- const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[owner][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[owner][zrxToken.address].plus(zrxWithdrawAmount),
- );
- expect(newBalances[forwarderContract.address][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[forwarderContract.address][zrxToken.address].minus(zrxWithdrawAmount),
- );
- });
- it('should revert if not called by owner', async () => {
- const zrxWithdrawAmount = erc20Balances[forwarderContract.address][zrxToken.address];
- await expectTransactionFailedAsync(
- forwarderWrapper.withdrawAssetAsync(zrxAssetData, zrxWithdrawAmount, { from: makerAddress }),
- RevertReason.OnlyContractOwner,
- );
- });
- });
-});
-// tslint:disable:max-file-line-count
-// tslint:enable:no-unnecessary-type-assertion
diff --git a/contracts/extensions/test/extensions/order_matcher.ts b/contracts/extensions/test/extensions/order_matcher.ts
deleted file mode 100644
index acb46ced4..000000000
--- a/contracts/extensions/test/extensions/order_matcher.ts
+++ /dev/null
@@ -1,818 +0,0 @@
-import {
- artifacts as protocolArtifacts,
- ERC20ProxyContract,
- ERC20Wrapper,
- ERC721ProxyContract,
- ExchangeContract,
- ExchangeFillEventArgs,
- ExchangeWrapper,
-} from '@0x/contracts-protocol';
-import {
- chaiSetup,
- constants,
- ERC20BalancesByOwner,
- expectContractCreationFailedAsync,
- expectTransactionFailedAsync,
- LogDecoder,
- OrderFactory,
- provider,
- sendTransactionResult,
- txDefaults,
- web3Wrapper,
-} from '@0x/contracts-test-utils';
-import { artifacts as tokenArtifacts, DummyERC20TokenContract, DummyERC721TokenContract } from '@0x/contracts-tokens';
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { assetDataUtils } from '@0x/order-utils';
-import { RevertReason } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import * as chai from 'chai';
-import { LogWithDecodedArgs } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { OrderMatcherContract } from '../../generated-wrappers/order_matcher';
-import { artifacts } from '../../src/artifacts';
-
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-chaiSetup.configure();
-const expect = chai.expect;
-// tslint:disable:no-unnecessary-type-assertion
-describe('OrderMatcher', () => {
- let makerAddressLeft: string;
- let makerAddressRight: string;
- let owner: string;
- let takerAddress: string;
- let feeRecipientAddressLeft: string;
- let feeRecipientAddressRight: string;
-
- let erc20TokenA: DummyERC20TokenContract;
- let erc20TokenB: DummyERC20TokenContract;
- let zrxToken: DummyERC20TokenContract;
- let exchange: ExchangeContract;
- let erc20Proxy: ERC20ProxyContract;
- let erc721Proxy: ERC721ProxyContract;
- let orderMatcher: OrderMatcherContract;
-
- let erc20BalancesByOwner: ERC20BalancesByOwner;
- let exchangeWrapper: ExchangeWrapper;
- let erc20Wrapper: ERC20Wrapper;
- let orderFactoryLeft: OrderFactory;
- let orderFactoryRight: OrderFactory;
-
- let leftMakerAssetData: string;
- let leftTakerAssetData: string;
- let defaultERC20MakerAssetAddress: string;
- let defaultERC20TakerAssetAddress: string;
-
- before(async () => {
- await blockchainLifecycle.startAsync();
- });
- after(async () => {
- await blockchainLifecycle.revertAsync();
- });
- before(async () => {
- // Create accounts
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- // Hack(albrow): Both Prettier and TSLint insert a trailing comma below
- // but that is invalid syntax as of TypeScript version >= 2.8. We don't
- // have the right fine-grained configuration options in TSLint,
- // Prettier, or TypeScript, to reconcile this, so we will just have to
- // wait for them to sort it out. We disable TSLint and Prettier for
- // this part of the code for now. This occurs several times in this
- // file. See https://github.com/prettier/prettier/issues/4624.
- // prettier-ignore
- const usedAddresses = ([
- owner,
- makerAddressLeft,
- makerAddressRight,
- takerAddress,
- feeRecipientAddressLeft,
- // tslint:disable-next-line:trailing-comma
- feeRecipientAddressRight
- ] = _.slice(accounts, 0, 6));
- // Create wrappers
- erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
- // Deploy ERC20 token & ERC20 proxy
- const numDummyErc20ToDeploy = 3;
- [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
- numDummyErc20ToDeploy,
- constants.DUMMY_TOKEN_DECIMALS,
- );
- erc20Proxy = await erc20Wrapper.deployProxyAsync();
- await erc20Wrapper.setBalancesAndAllowancesAsync();
- // Deploy ERC721 proxy
- erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
- protocolArtifacts.ERC721Proxy,
- provider,
- txDefaults,
- );
- // Depoy exchange
- exchange = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- assetDataUtils.encodeERC20AssetData(zrxToken.address),
- );
- exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
- // Authorize ERC20 trades by exchange
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
- from: owner,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- // Deploy OrderMatcher
- orderMatcher = await OrderMatcherContract.deployFrom0xArtifactAsync(
- artifacts.OrderMatcher,
- provider,
- txDefaults,
- exchange.address,
- );
- // Set default addresses
- defaultERC20MakerAssetAddress = erc20TokenA.address;
- defaultERC20TakerAssetAddress = erc20TokenB.address;
- leftMakerAssetData = assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress);
- leftTakerAssetData = assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress);
- // Set OrderMatcher balances and allowances
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenA.setBalance.sendTransactionAsync(orderMatcher.address, constants.INITIAL_ERC20_BALANCE, {
- from: owner,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20TokenB.setBalance.sendTransactionAsync(orderMatcher.address, constants.INITIAL_ERC20_BALANCE, {
- from: owner,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(
- leftMakerAssetData,
- constants.INITIAL_ERC20_ALLOWANCE,
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(
- leftTakerAssetData,
- constants.INITIAL_ERC20_ALLOWANCE,
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- // Create default order parameters
- const defaultOrderParamsLeft = {
- ...constants.STATIC_ORDER_PARAMS,
- makerAddress: makerAddressLeft,
- exchangeAddress: exchange.address,
- makerAssetData: leftMakerAssetData,
- takerAssetData: leftTakerAssetData,
- feeRecipientAddress: feeRecipientAddressLeft,
- makerFee: constants.ZERO_AMOUNT,
- takerFee: constants.ZERO_AMOUNT,
- };
- const defaultOrderParamsRight = {
- ...constants.STATIC_ORDER_PARAMS,
- makerAddress: makerAddressRight,
- exchangeAddress: exchange.address,
- makerAssetData: leftTakerAssetData,
- takerAssetData: leftMakerAssetData,
- feeRecipientAddress: feeRecipientAddressRight,
- makerFee: constants.ZERO_AMOUNT,
- takerFee: constants.ZERO_AMOUNT,
- };
- 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);
- });
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
- describe('constructor', () => {
- it('should revert if assetProxy is unregistered', async () => {
- const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- constants.NULL_BYTES,
- );
- return expectContractCreationFailedAsync(
- (OrderMatcherContract.deployFrom0xArtifactAsync(
- artifacts.OrderMatcher,
- provider,
- txDefaults,
- exchangeInstance.address,
- ) as any) as sendTransactionResult,
- RevertReason.UnregisteredAssetProxy,
- );
- });
- });
- describe('matchOrders', () => {
- beforeEach(async () => {
- erc20BalancesByOwner = await erc20Wrapper.getBalancesAsync();
- });
- it('should revert if not called by owner', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
- });
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await expectTransactionFailedAsync(
- web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: takerAddress,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- RevertReason.OnlyContractOwner,
- );
- });
- it('should transfer the correct amounts when orders completely fill each other', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
- });
- // Match signedOrderLeft with signedOrderRight
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: signedOrderLeft.makerAssetAmount,
- amountBoughtByLeftMaker: signedOrderLeft.takerAssetAmount,
- // Right Maker
- amountSoldByRightMaker: signedOrderRight.makerAssetAmount,
- amountBoughtByRightMaker: signedOrderRight.takerAssetAmount,
- // Taker
- leftMakerAssetSpreadAmount: signedOrderLeft.makerAssetAmount.minus(signedOrderRight.takerAssetAmount),
- };
- const initialLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const newErc20Balances = await erc20Wrapper.getBalancesAsync();
- expect(newErc20Balances[makerAddressLeft][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20MakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20TakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(newErc20Balances[makerAddressLeft][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20TakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20MakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- expect(newLeftMakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftMakerAssetTakerBalance.plus(expectedTransferAmounts.leftMakerAssetSpreadAmount),
- );
- });
- it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- });
- // Match signedOrderLeft with signedOrderRight
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: signedOrderLeft.makerAssetAmount,
- amountBoughtByLeftMaker: signedOrderLeft.takerAssetAmount,
- // Right Maker
- amountSoldByRightMaker: signedOrderRight.makerAssetAmount,
- amountBoughtByRightMaker: signedOrderRight.takerAssetAmount,
- };
- const initialLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const newErc20Balances = await erc20Wrapper.getBalancesAsync();
- expect(newErc20Balances[makerAddressLeft][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20MakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20TakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(newErc20Balances[makerAddressLeft][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20TakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20MakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- expect(newLeftMakerAssetTakerBalance).to.be.bignumber.equal(initialLeftMakerAssetTakerBalance);
- });
- it('should transfer the correct amounts when left order is completely filled and right order would be partially filled', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18),
- });
- // Match signedOrderLeft with signedOrderRight
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: signedOrderLeft.makerAssetAmount,
- amountBoughtByLeftMaker: signedOrderLeft.takerAssetAmount,
- // Right Maker
- amountSoldByRightMaker: signedOrderRight.makerAssetAmount,
- amountBoughtByRightMaker: signedOrderRight.takerAssetAmount,
- // Taker
- leftMakerAssetSpreadAmount: signedOrderLeft.makerAssetAmount.minus(signedOrderRight.takerAssetAmount),
- leftTakerAssetSpreadAmount: signedOrderRight.makerAssetAmount.minus(signedOrderLeft.takerAssetAmount),
- };
- const initialLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const initialLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- // Match signedOrderLeft with signedOrderRight
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const newLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- const newErc20Balances = await erc20Wrapper.getBalancesAsync();
- expect(newErc20Balances[makerAddressLeft][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20MakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20TakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(newErc20Balances[makerAddressLeft][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20TakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20MakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- expect(newLeftMakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftMakerAssetTakerBalance.plus(expectedTransferAmounts.leftMakerAssetSpreadAmount),
- );
- expect(newLeftTakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftTakerAssetTakerBalance.plus(expectedTransferAmounts.leftTakerAssetSpreadAmount),
- );
- });
- it('should not call fillOrder when rightOrder is completely filled after matchOrders call and orders were never partially filled', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
- });
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- const logDecoder = new LogDecoder(web3Wrapper, { ...artifacts, ...tokenArtifacts, ...protocolArtifacts });
- const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- );
- const fillLogs = _.filter(
- txReceipt.logs,
- log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
- );
- // Only 2 Fill logs should exist for `matchOrders` call. `fillOrder` should not have been called and should not have emitted a Fill event.
- expect(fillLogs.length).to.be.equal(2);
- });
- it('should not call fillOrder when rightOrder is completely filled after matchOrders call and orders were initially partially filled', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
- });
- await exchangeWrapper.fillOrderAsync(signedOrderLeft, takerAddress, {
- takerAssetFillAmount: signedOrderLeft.takerAssetAmount.dividedToIntegerBy(5),
- });
- await exchangeWrapper.fillOrderAsync(signedOrderRight, takerAddress, {
- takerAssetFillAmount: signedOrderRight.takerAssetAmount.dividedToIntegerBy(5),
- });
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- const logDecoder = new LogDecoder(web3Wrapper, { ...artifacts, ...tokenArtifacts, ...protocolArtifacts });
- const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- );
- const fillLogs = _.filter(
- txReceipt.logs,
- log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
- );
- // Only 2 Fill logs should exist for `matchOrders` call. `fillOrder` should not have been called and should not have emitted a Fill event.
- expect(fillLogs.length).to.be.equal(2);
- });
- it('should only take a spread in rightMakerAsset if entire leftMakerAssetSpread amount can be used to fill rightOrder after matchOrders call', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.9), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(990), 18),
- });
- const initialLeftMakerAssetSpreadAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1.09), 18);
- const leftTakerAssetSpreadAmount = initialLeftMakerAssetSpreadAmount
- .times(signedOrderRight.makerAssetAmount)
- .dividedToIntegerBy(signedOrderRight.takerAssetAmount);
- // Match signedOrderLeft with signedOrderRight
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: signedOrderLeft.makerAssetAmount,
- amountBoughtByLeftMaker: signedOrderLeft.takerAssetAmount,
- // Right Maker
- amountSoldByRightMaker: signedOrderLeft.takerAssetAmount.plus(leftTakerAssetSpreadAmount),
- amountBoughtByRightMaker: signedOrderLeft.makerAssetAmount,
- // Taker
- leftMakerAssetSpreadAmount: constants.ZERO_AMOUNT,
- leftTakerAssetSpreadAmount,
- };
- const initialLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const initialLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- // Match signedOrderLeft with signedOrderRight
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const newLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- const newErc20Balances = await erc20Wrapper.getBalancesAsync();
- expect(newErc20Balances[makerAddressLeft][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20MakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20TakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(newErc20Balances[makerAddressLeft][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20TakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20MakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- expect(newLeftMakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftMakerAssetTakerBalance.plus(expectedTransferAmounts.leftMakerAssetSpreadAmount),
- );
- expect(newLeftTakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftTakerAssetTakerBalance.plus(expectedTransferAmounts.leftTakerAssetSpreadAmount),
- );
- });
- it("should succeed if rightOrder's makerAssetData and takerAssetData are not provided", async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18),
- });
- // Match signedOrderLeft with signedOrderRight
- const expectedTransferAmounts = {
- // Left Maker
- amountSoldByLeftMaker: signedOrderLeft.makerAssetAmount,
- amountBoughtByLeftMaker: signedOrderLeft.takerAssetAmount,
- // Right Maker
- amountSoldByRightMaker: signedOrderRight.makerAssetAmount,
- amountBoughtByRightMaker: signedOrderRight.takerAssetAmount,
- // Taker
- leftMakerAssetSpreadAmount: signedOrderLeft.makerAssetAmount.minus(signedOrderRight.takerAssetAmount),
- leftTakerAssetSpreadAmount: signedOrderRight.makerAssetAmount.minus(signedOrderLeft.takerAssetAmount),
- };
- const initialLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const initialLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- // Match signedOrderLeft with signedOrderRight
- signedOrderRight.makerAssetData = constants.NULL_BYTES;
- signedOrderRight.takerAssetData = constants.NULL_BYTES;
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newLeftMakerAssetTakerBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- const newLeftTakerAssetTakerBalance = await erc20TokenB.balanceOf.callAsync(orderMatcher.address);
- const newErc20Balances = await erc20Wrapper.getBalancesAsync();
- expect(newErc20Balances[makerAddressLeft][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20MakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20TakerAssetAddress].minus(
- expectedTransferAmounts.amountSoldByRightMaker,
- ),
- );
- expect(newErc20Balances[makerAddressLeft][defaultERC20TakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressLeft][defaultERC20TakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByLeftMaker,
- ),
- );
- expect(newErc20Balances[makerAddressRight][defaultERC20MakerAssetAddress]).to.be.bignumber.equal(
- erc20BalancesByOwner[makerAddressRight][defaultERC20MakerAssetAddress].plus(
- expectedTransferAmounts.amountBoughtByRightMaker,
- ),
- );
- expect(newLeftMakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftMakerAssetTakerBalance.plus(expectedTransferAmounts.leftMakerAssetSpreadAmount),
- );
- expect(newLeftTakerAssetTakerBalance).to.be.bignumber.equal(
- initialLeftTakerAssetTakerBalance.plus(expectedTransferAmounts.leftTakerAssetSpreadAmount),
- );
- });
- it('should revert with the correct reason if matchOrders call reverts', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- });
- signedOrderRight.signature = `0xff${signedOrderRight.signature.slice(4)}`;
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await expectTransactionFailedAsync(
- web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- RevertReason.InvalidOrderSignature,
- );
- });
- it('should revert with the correct reason if fillOrder call reverts', async () => {
- // Create orders to match
- const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
- });
- const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
- makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18),
- takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18),
- });
- // Matcher will not have enough allowance to fill rightOrder
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(leftMakerAssetData, constants.ZERO_AMOUNT, {
- from: owner,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const data = exchange.matchOrders.getABIEncodedTransactionData(
- signedOrderLeft,
- signedOrderRight,
- signedOrderLeft.signature,
- signedOrderRight.signature,
- );
- await expectTransactionFailedAsync(
- web3Wrapper.sendTransactionAsync({
- data,
- to: orderMatcher.address,
- from: owner,
- gas: constants.MAX_MATCH_ORDERS_GAS,
- }),
- RevertReason.TransferFailed,
- );
- });
- });
- describe('withdrawAsset', () => {
- it('should allow owner to withdraw ERC20 tokens', async () => {
- const erc20AWithdrawAmount = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- expect(erc20AWithdrawAmount).to.be.bignumber.gt(constants.ZERO_AMOUNT);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.withdrawAsset.sendTransactionAsync(leftMakerAssetData, erc20AWithdrawAmount, {
- from: owner,
- }),
- );
- const newBalance = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- expect(newBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should allow owner to withdraw ERC721 tokens', async () => {
- const erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
- tokenArtifacts.DummyERC721Token,
- provider,
- txDefaults,
- constants.DUMMY_TOKEN_NAME,
- constants.DUMMY_TOKEN_SYMBOL,
- );
- const tokenId = new BigNumber(1);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(orderMatcher.address, tokenId, { from: owner }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
- const withdrawAmount = new BigNumber(1);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.withdrawAsset.sendTransactionAsync(assetData, withdrawAmount, { from: owner }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const erc721Owner = await erc721Token.ownerOf.callAsync(tokenId);
- expect(erc721Owner).to.be.equal(owner);
- });
- it('should revert if not called by owner', async () => {
- const erc20AWithdrawAmount = await erc20TokenA.balanceOf.callAsync(orderMatcher.address);
- expect(erc20AWithdrawAmount).to.be.bignumber.gt(constants.ZERO_AMOUNT);
- await expectTransactionFailedAsync(
- orderMatcher.withdrawAsset.sendTransactionAsync(leftMakerAssetData, erc20AWithdrawAmount, {
- from: takerAddress,
- }),
- RevertReason.OnlyContractOwner,
- );
- });
- });
- describe('approveAssetProxy', () => {
- it('should be able to set an allowance for ERC20 tokens', async () => {
- const allowance = new BigNumber(55465465426546);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(leftMakerAssetData, allowance, {
- from: owner,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const newAllowance = await erc20TokenA.allowance.callAsync(orderMatcher.address, erc20Proxy.address);
- expect(newAllowance).to.be.bignumber.equal(allowance);
- });
- it('should be able to approve an ERC721 token by passing in allowance = 1', async () => {
- const erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
- tokenArtifacts.DummyERC721Token,
- provider,
- txDefaults,
- constants.DUMMY_TOKEN_NAME,
- constants.DUMMY_TOKEN_SYMBOL,
- );
- const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, constants.ZERO_AMOUNT);
- const allowance = new BigNumber(1);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = await erc721Token.isApprovedForAll.callAsync(orderMatcher.address, erc721Proxy.address);
- expect(isApproved).to.be.equal(true);
- });
- it('should be able to approve an ERC721 token by passing in allowance > 1', async () => {
- const erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
- tokenArtifacts.DummyERC721Token,
- provider,
- txDefaults,
- constants.DUMMY_TOKEN_NAME,
- constants.DUMMY_TOKEN_SYMBOL,
- );
- const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, constants.ZERO_AMOUNT);
- const allowance = new BigNumber(2);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = await erc721Token.isApprovedForAll.callAsync(orderMatcher.address, erc721Proxy.address);
- expect(isApproved).to.be.equal(true);
- });
- it('should revert if not called by owner', async () => {
- const approval = new BigNumber(1);
- await expectTransactionFailedAsync(
- orderMatcher.approveAssetProxy.sendTransactionAsync(leftMakerAssetData, approval, {
- from: takerAddress,
- }),
- RevertReason.OnlyContractOwner,
- );
- });
- });
-});
-// tslint:disable:max-file-line-count
-// tslint:enable:no-unnecessary-type-assertion
diff --git a/contracts/extensions/test/extensions/order_validator.ts b/contracts/extensions/test/extensions/order_validator.ts
deleted file mode 100644
index 7d8675f36..000000000
--- a/contracts/extensions/test/extensions/order_validator.ts
+++ /dev/null
@@ -1,609 +0,0 @@
-import {
- artifacts as protocolArtifacts,
- ERC20ProxyContract,
- ERC20Wrapper,
- ERC721ProxyContract,
- ERC721Wrapper,
- ExchangeContract,
- ExchangeWrapper,
-} from '@0x/contracts-protocol';
-import {
- chaiSetup,
- constants,
- OrderFactory,
- OrderStatus,
- provider,
- txDefaults,
- web3Wrapper,
-} from '@0x/contracts-test-utils';
-import { DummyERC20TokenContract, DummyERC721TokenContract } from '@0x/contracts-tokens';
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import * as chai from 'chai';
-import * as _ from 'lodash';
-
-import { OrderValidatorContract } from '../../generated-wrappers/order_validator';
-import { artifacts } from '../../src/artifacts/index';
-
-chaiSetup.configure();
-const expect = chai.expect;
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('OrderValidator', () => {
- let makerAddress: string;
- let owner: string;
- let takerAddress: string;
- let erc20AssetData: string;
- let erc721AssetData: string;
-
- let erc20Token: DummyERC20TokenContract;
- let zrxToken: DummyERC20TokenContract;
- let erc721Token: DummyERC721TokenContract;
- let exchange: ExchangeContract;
- let orderValidator: OrderValidatorContract;
- let erc20Proxy: ERC20ProxyContract;
- let erc721Proxy: ERC721ProxyContract;
-
- let signedOrder: SignedOrder;
- let signedOrder2: SignedOrder;
- let orderFactory: OrderFactory;
-
- const tokenId = new BigNumber(123456789);
- const tokenId2 = new BigNumber(987654321);
- const ERC721_BALANCE = new BigNumber(1);
- const ERC721_ALLOWANCE = new BigNumber(1);
-
- before(async () => {
- await blockchainLifecycle.startAsync();
- });
- after(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
- before(async () => {
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const usedAddresses = ([owner, makerAddress, takerAddress] = _.slice(accounts, 0, 3));
-
- const erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
- const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
-
- const numDummyErc20ToDeploy = 2;
- [erc20Token, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
- numDummyErc20ToDeploy,
- constants.DUMMY_TOKEN_DECIMALS,
- );
- erc20Proxy = await erc20Wrapper.deployProxyAsync();
-
- [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
- erc721Proxy = await erc721Wrapper.deployProxyAsync();
-
- const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- exchange = await ExchangeContract.deployFrom0xArtifactAsync(
- protocolArtifacts.Exchange,
- provider,
- txDefaults,
- zrxAssetData,
- );
- const exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
-
- orderValidator = await OrderValidatorContract.deployFrom0xArtifactAsync(
- artifacts.OrderValidator,
- provider,
- txDefaults,
- exchange.address,
- zrxAssetData,
- );
-
- erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
- erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
- const defaultOrderParams = {
- ...constants.STATIC_ORDER_PARAMS,
- exchangeAddress: exchange.address,
- makerAddress,
- feeRecipientAddress: constants.NULL_ADDRESS,
- makerAssetData: erc20AssetData,
- takerAssetData: erc721AssetData,
- };
- const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
- orderFactory = new OrderFactory(privateKey, defaultOrderParams);
- });
-
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
- describe('getBalanceAndAllowance', () => {
- describe('getERC721TokenOwner', async () => {
- it('should return the null address when tokenId is not owned', async () => {
- const tokenOwner = await orderValidator.getERC721TokenOwner.callAsync(makerAddress, tokenId);
- expect(tokenOwner).to.be.equal(constants.NULL_ADDRESS);
- });
- it('should return the owner address when tokenId is owned', async () => {
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const tokenOwner = await orderValidator.getERC721TokenOwner.callAsync(erc721Token.address, tokenId);
- expect(tokenOwner).to.be.equal(makerAddress);
- });
- });
- describe('ERC20 assetData', () => {
- it('should return the correct balances and allowances when both values are 0', async () => {
- const [newBalance, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc20AssetData,
- );
- expect(constants.ZERO_AMOUNT).to.be.bignumber.equal(newBalance);
- expect(constants.ZERO_AMOUNT).to.be.bignumber.equal(newAllowance);
- });
- it('should return the correct balance and allowance when both values are non-zero', async () => {
- const balance = new BigNumber(123);
- const allowance = new BigNumber(456);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, balance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [newBalance, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc20AssetData,
- );
- expect(balance).to.be.bignumber.equal(newBalance);
- expect(allowance).to.be.bignumber.equal(newAllowance);
- });
- });
- describe('ERC721 assetData', () => {
- it('should return a balance of 0 when the tokenId is not owned by target', async () => {
- const [newBalance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc721AssetData,
- );
- expect(newBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return an allowance of 0 when no approval is set', async () => {
- const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc721AssetData,
- );
- expect(newAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return a balance of 1 when the tokenId is owned by target', async () => {
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [newBalance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc721AssetData,
- );
- expect(newBalance).to.be.bignumber.equal(ERC721_BALANCE);
- });
- it('should return an allowance of 1 when ERC721Proxy is approved for all', async () => {
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc721AssetData,
- );
- expect(newAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- });
- it('should return an allowance of 0 when ERC721Proxy is approved for specific tokenId', async () => {
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.approve.sendTransactionAsync(erc721Proxy.address, tokenId, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
- makerAddress,
- erc721AssetData,
- );
- expect(newAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- });
- });
- describe('getBalancesAndAllowances', () => {
- it('should return the correct balances and allowances when all values are 0', async () => {
- const [
- [erc20Balance, erc721Balance],
- [erc20Allowance, erc721Allowance],
- ] = await orderValidator.getBalancesAndAllowances.callAsync(makerAddress, [
- erc20AssetData,
- erc721AssetData,
- ]);
- expect(erc20Balance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(erc721Balance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(erc20Allowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(erc721Allowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return the correct balances and allowances when balances and allowances are non-zero', async () => {
- const balance = new BigNumber(123);
- const allowance = new BigNumber(456);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, balance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [
- [erc20Balance, erc721Balance],
- [erc20Allowance, erc721Allowance],
- ] = await orderValidator.getBalancesAndAllowances.callAsync(makerAddress, [
- erc20AssetData,
- erc721AssetData,
- ]);
- expect(erc20Balance).to.be.bignumber.equal(balance);
- expect(erc721Balance).to.be.bignumber.equal(ERC721_BALANCE);
- expect(erc20Allowance).to.be.bignumber.equal(allowance);
- expect(erc721Allowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- });
- });
- describe('getTraderInfo', () => {
- beforeEach(async () => {
- signedOrder = await orderFactory.newSignedOrderAsync();
- });
- it('should return the correct info when no balances or allowances are set', async () => {
- const traderInfo = await orderValidator.getTraderInfo.callAsync(signedOrder, takerAddress);
- expect(traderInfo.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return the correct info when balances and allowances are set', async () => {
- const makerBalance = new BigNumber(123);
- const makerAllowance = new BigNumber(456);
- const makerZrxBalance = new BigNumber(789);
- const takerZrxAllowance = new BigNumber(987);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const traderInfo = await orderValidator.getTraderInfo.callAsync(signedOrder, takerAddress);
- expect(traderInfo.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
- expect(traderInfo.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- });
- });
- describe('getTradersInfo', () => {
- beforeEach(async () => {
- signedOrder = await orderFactory.newSignedOrderAsync();
- signedOrder2 = await orderFactory.newSignedOrderAsync({
- takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId2),
- });
- });
- it('should return the correct info when no balances or allowances have been set', async () => {
- const orders = [signedOrder, signedOrder2];
- const takers = [takerAddress, takerAddress];
- const [traderInfo1, traderInfo2] = await orderValidator.getTradersInfo.callAsync(orders, takers);
- expect(traderInfo1.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return the correct info when balances and allowances are set', async () => {
- const makerBalance = new BigNumber(123);
- const makerAllowance = new BigNumber(456);
- const makerZrxBalance = new BigNumber(789);
- const takerZrxAllowance = new BigNumber(987);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId2),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const orders = [signedOrder, signedOrder2];
- const takers = [takerAddress, takerAddress];
- const [traderInfo1, traderInfo2] = await orderValidator.getTradersInfo.callAsync(orders, takers);
-
- expect(traderInfo1.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo1.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- expect(traderInfo2.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo2.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo2.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
- expect(traderInfo2.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- });
- });
- describe('getOrderAndTraderInfo', () => {
- beforeEach(async () => {
- signedOrder = await orderFactory.newSignedOrderAsync();
- });
- it('should return the correct info when no balances or allowances are set', async () => {
- const [orderInfo, traderInfo] = await orderValidator.getOrderAndTraderInfo.callAsync(
- signedOrder,
- takerAddress,
- );
- const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
- expect(orderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
- expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return the correct info when balances and allowances are set', async () => {
- const makerBalance = new BigNumber(123);
- const makerAllowance = new BigNumber(456);
- const makerZrxBalance = new BigNumber(789);
- const takerZrxAllowance = new BigNumber(987);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const [orderInfo, traderInfo] = await orderValidator.getOrderAndTraderInfo.callAsync(
- signedOrder,
- takerAddress,
- );
- const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
- expect(orderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
- expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
- expect(traderInfo.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- });
- });
- describe('getOrdersAndTradersInfo', () => {
- beforeEach(async () => {
- signedOrder = await orderFactory.newSignedOrderAsync();
- signedOrder2 = await orderFactory.newSignedOrderAsync({
- takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId2),
- });
- });
- it('should return the correct info when no balances or allowances have been set', async () => {
- const orders = [signedOrder, signedOrder2];
- const takers = [takerAddress, takerAddress];
- const [
- [orderInfo1, orderInfo2],
- [traderInfo1, traderInfo2],
- ] = await orderValidator.getOrdersAndTradersInfo.callAsync(orders, takers);
- const expectedOrderHash1 = orderHashUtils.getOrderHashHex(signedOrder);
- const expectedOrderHash2 = orderHashUtils.getOrderHashHex(signedOrder2);
- expect(orderInfo1.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo1.orderHash).to.be.equal(expectedOrderHash1);
- expect(orderInfo1.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(orderInfo2.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo2.orderHash).to.be.equal(expectedOrderHash2);
- expect(orderInfo2.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- });
- it('should return the correct info when balances and allowances are set', async () => {
- const makerBalance = new BigNumber(123);
- const makerAllowance = new BigNumber(456);
- const makerZrxBalance = new BigNumber(789);
- const takerZrxAllowance = new BigNumber(987);
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
- from: makerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const isApproved = true;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
- from: takerAddress,
- }),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId2),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const orders = [signedOrder, signedOrder2];
- const takers = [takerAddress, takerAddress];
- const [
- [orderInfo1, orderInfo2],
- [traderInfo1, traderInfo2],
- ] = await orderValidator.getOrdersAndTradersInfo.callAsync(orders, takers);
- const expectedOrderHash1 = orderHashUtils.getOrderHashHex(signedOrder);
- const expectedOrderHash2 = orderHashUtils.getOrderHashHex(signedOrder2);
- expect(orderInfo1.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo1.orderHash).to.be.equal(expectedOrderHash1);
- expect(orderInfo1.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(orderInfo2.orderStatus).to.be.equal(OrderStatus.Fillable);
- expect(orderInfo2.orderHash).to.be.equal(expectedOrderHash2);
- expect(orderInfo2.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo1.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- expect(traderInfo2.makerBalance).to.be.bignumber.equal(makerBalance);
- expect(traderInfo2.makerAllowance).to.be.bignumber.equal(makerAllowance);
- expect(traderInfo2.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
- expect(traderInfo2.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
- expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
- expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
- expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
- });
- });
-});
-// tslint:disable:max-file-line-count
diff --git a/contracts/extensions/test/global_hooks.ts b/contracts/extensions/test/global_hooks.ts
deleted file mode 100644
index f8ace376a..000000000
--- a/contracts/extensions/test/global_hooks.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { env, EnvVars } from '@0x/dev-utils';
-
-import { coverage, profiler, provider } from '@0x/contracts-test-utils';
-before('start web3 provider', () => {
- provider.start();
-});
-after('generate coverage report', async () => {
- if (env.parseBoolean(EnvVars.SolidityCoverage)) {
- const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
- await coverageSubprovider.writeCoverageAsync();
- }
- if (env.parseBoolean(EnvVars.SolidityProfiler)) {
- const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
- await profilerSubprovider.writeProfilerOutputAsync();
- }
- provider.stop();
-});
diff --git a/contracts/extensions/test/utils/balance_threshold_wrapper.ts b/contracts/extensions/test/utils/balance_threshold_wrapper.ts
deleted file mode 100644
index 28a4ef011..000000000
--- a/contracts/extensions/test/utils/balance_threshold_wrapper.ts
+++ /dev/null
@@ -1,283 +0,0 @@
-import { artifacts as protocolArtifacts, ExchangeContract } from '@0x/contracts-protocol';
-import {
- FillResults,
- formatters,
- LogDecoder,
- OrderInfo,
- orderUtils,
- TransactionFactory,
-} from '@0x/contracts-test-utils';
-import { artifacts as tokensArtifacts } from '@0x/contracts-tokens';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter';
-import { artifacts } from '../../src/artifacts';
-
-export class BalanceThresholdWrapper {
- private readonly _balanceThresholdFilter: BalanceThresholdFilterContract;
- private readonly _signerTransactionFactory: TransactionFactory;
- private readonly _exchange: ExchangeContract;
- private readonly _web3Wrapper: Web3Wrapper;
- private readonly _logDecoder: LogDecoder;
- constructor(
- balanceThresholdFilter: BalanceThresholdFilterContract,
- exchangeContract: ExchangeContract,
- signerTransactionFactory: TransactionFactory,
- provider: Provider,
- ) {
- this._balanceThresholdFilter = balanceThresholdFilter;
- this._exchange = exchangeContract;
- this._signerTransactionFactory = signerTransactionFactory;
- this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper, {
- ...artifacts,
- ...tokensArtifacts,
- ...protocolArtifacts,
- });
- }
- public async fillOrderAsync(
- signedOrder: SignedOrder,
- from: string,
- opts: { takerAssetFillAmount?: BigNumber } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
- const data = this._exchange.fillOrder.getABIEncodedTransactionData(
- params.order,
- params.takerAssetFillAmount,
- params.signature,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async fillOrKillOrderAsync(
- signedOrder: SignedOrder,
- from: string,
- opts: { takerAssetFillAmount?: BigNumber } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
- const data = this._exchange.fillOrKillOrder.getABIEncodedTransactionData(
- params.order,
- params.takerAssetFillAmount,
- params.signature,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async fillOrderNoThrowAsync(
- signedOrder: SignedOrder,
- from: string,
- opts: { takerAssetFillAmount?: BigNumber; gas?: number } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
- const data = this._exchange.fillOrderNoThrow.getABIEncodedTransactionData(
- params.order,
- params.takerAssetFillAmount,
- params.signature,
- );
- const txReceipt = this._executeTransactionAsync(data, from, opts.gas);
- return txReceipt;
- }
- public async batchFillOrdersAsync(
- orders: SignedOrder[],
- from: string,
- opts: { takerAssetFillAmounts?: BigNumber[] } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
- const data = this._exchange.batchFillOrders.getABIEncodedTransactionData(
- params.orders,
- params.takerAssetFillAmounts,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async batchFillOrKillOrdersAsync(
- orders: SignedOrder[],
- from: string,
- opts: { takerAssetFillAmounts?: BigNumber[] } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
- const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData(
- params.orders,
- params.takerAssetFillAmounts,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async batchFillOrdersNoThrowAsync(
- orders: SignedOrder[],
- from: string,
- opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
- const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData(
- params.orders,
- params.takerAssetFillAmounts,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from, opts.gas);
- return txReceipt;
- }
- public async marketSellOrdersAsync(
- orders: SignedOrder[],
- from: string,
- opts: { takerAssetFillAmount: BigNumber },
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount);
- const data = this._exchange.marketSellOrders.getABIEncodedTransactionData(
- params.orders,
- params.takerAssetFillAmount,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async marketSellOrdersNoThrowAsync(
- orders: SignedOrder[],
- from: string,
- opts: { takerAssetFillAmount: BigNumber; gas?: number },
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount);
- const data = this._exchange.marketSellOrdersNoThrow.getABIEncodedTransactionData(
- params.orders,
- params.takerAssetFillAmount,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from, opts.gas);
- return txReceipt;
- }
- public async marketBuyOrdersAsync(
- orders: SignedOrder[],
- from: string,
- opts: { makerAssetFillAmount: BigNumber },
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount);
- const data = this._exchange.marketBuyOrders.getABIEncodedTransactionData(
- params.orders,
- params.makerAssetFillAmount,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async marketBuyOrdersNoThrowAsync(
- orders: SignedOrder[],
- from: string,
- opts: { makerAssetFillAmount: BigNumber; gas?: number },
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount);
- const data = this._exchange.marketBuyOrdersNoThrow.getABIEncodedTransactionData(
- params.orders,
- params.makerAssetFillAmount,
- params.signatures,
- );
- const txReceipt = this._executeTransactionAsync(data, from, opts.gas);
- return txReceipt;
- }
- public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise<TransactionReceiptWithDecodedLogs> {
- const params = orderUtils.createCancel(signedOrder);
- const data = this._exchange.cancelOrder.getABIEncodedTransactionData(params.order);
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async batchCancelOrdersAsync(
- orders: SignedOrder[],
- from: string,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = formatters.createBatchCancel(orders);
- const data = this._exchange.batchCancelOrders.getABIEncodedTransactionData(params.orders);
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
- const data = this._exchange.cancelOrdersUpTo.getABIEncodedTransactionData(salt);
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
- const filledAmount = await this._exchange.filled.callAsync(orderHashHex);
- return filledAmount;
- }
- public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
- const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex);
- return isCancelled;
- }
- public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
- const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress);
- return orderEpoch;
- }
- public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
- const orderInfo = await this._exchange.getOrderInfo.callAsync(signedOrder);
- return orderInfo;
- }
- public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise<OrderInfo[]> {
- const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[];
- return ordersInfo;
- }
- public async matchOrdersAsync(
- signedOrderLeft: SignedOrder,
- signedOrderRight: SignedOrder,
- from: string,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
- const data = await this._exchange.matchOrders.getABIEncodedTransactionData(
- params.left,
- params.right,
- params.leftSignature,
- params.rightSignature,
- );
- const txReceipt = this._executeTransactionAsync(data, from);
- return txReceipt;
- }
- public async getFillOrderResultsAsync(
- signedOrder: SignedOrder,
- from: string,
- opts: { takerAssetFillAmount?: BigNumber } = {},
- ): Promise<FillResults> {
- const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
- const fillResults = await this._exchange.fillOrder.callAsync(
- params.order,
- params.takerAssetFillAmount,
- params.signature,
- { from },
- );
- return fillResults;
- }
- public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string {
- const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
- const data = this._exchange.fillOrder.getABIEncodedTransactionData(
- params.order,
- params.takerAssetFillAmount,
- params.signature,
- );
- return data;
- }
- public getBalanceThresholdAddress(): string {
- return this._balanceThresholdFilter.address;
- }
- public getExchangeAddress(): string {
- return this._exchange.address;
- }
- private async _executeTransactionAsync(
- abiEncodedExchangeTxData: string,
- from: string,
- gas?: number,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const signedExchangeTx = this._signerTransactionFactory.newSignedTransaction(abiEncodedExchangeTxData);
- const txOpts = _.isUndefined(gas) ? { from } : { from, gas };
- const txHash = await this._balanceThresholdFilter.executeTransaction.sendTransactionAsync(
- signedExchangeTx.salt,
- signedExchangeTx.signerAddress,
- signedExchangeTx.data,
- signedExchangeTx.signature,
- txOpts,
- );
- const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return txReceipt;
- }
-}
diff --git a/contracts/extensions/test/utils/dutch_auction_test_wrapper.ts b/contracts/extensions/test/utils/dutch_auction_test_wrapper.ts
deleted file mode 100644
index c1e2f2070..000000000
--- a/contracts/extensions/test/utils/dutch_auction_test_wrapper.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { artifacts as protocolArtifacts } from '@0x/contracts-protocol';
-import { LogDecoder } from '@0x/contracts-test-utils';
-import { artifacts as tokensArtifacts } from '@0x/contracts-tokens';
-import { DutchAuctionDetails, SignedOrder } from '@0x/types';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
-import { artifacts } from '../../src/artifacts';
-
-export class DutchAuctionTestWrapper {
- private readonly _dutchAuctionContract: DutchAuctionContract;
- private readonly _web3Wrapper: Web3Wrapper;
- private readonly _logDecoder: LogDecoder;
-
- constructor(contractInstance: DutchAuctionContract, provider: Provider) {
- this._dutchAuctionContract = contractInstance;
- this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper, {
- ...artifacts,
- ...tokensArtifacts,
- ...protocolArtifacts,
- });
- }
- /**
- * Matches the buy and sell orders at an amount given the following: the current block time, the auction
- * start time and the auction begin amount. The sell order is a an order at the lowest amount
- * at the end of the auction. Excess from the match is transferred to the seller.
- * Over time the price moves from beginAmount to endAmount given the current block.timestamp.
- * @param buyOrder The Buyer's order. This order is for the current expected price of the auction.
- * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
- * @param from Address the transaction is being sent from.
- * @return Transaction receipt with decoded logs.
- */
- public async matchOrdersAsync(
- buyOrder: SignedOrder,
- sellOrder: SignedOrder,
- from: string,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const txHash = await this._dutchAuctionContract.matchOrders.sendTransactionAsync(
- buyOrder,
- sellOrder,
- buyOrder.signature,
- sellOrder.signature,
- {
- from,
- },
- );
- const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return tx;
- }
- /**
- * Calculates the Auction Details for the given order
- * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
- * @return The dutch auction details.
- */
- public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> {
- const auctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
- return auctionDetails;
- }
-}
diff --git a/contracts/extensions/test/utils/forwarder_wrapper.ts b/contracts/extensions/test/utils/forwarder_wrapper.ts
deleted file mode 100644
index 4a43be04a..000000000
--- a/contracts/extensions/test/utils/forwarder_wrapper.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import { artifacts as protocolArtifacts } from '@0x/contracts-protocol';
-import { constants, formatters, LogDecoder, MarketSellOrders } from '@0x/contracts-test-utils';
-import { artifacts as tokensArtifacts } from '@0x/contracts-tokens';
-import { SignedOrder } from '@0x/types';
-import { BigNumber } from '@0x/utils';
-import { Web3Wrapper } from '@0x/web3-wrapper';
-import { Provider, TransactionReceiptWithDecodedLogs, TxDataPayable } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { ForwarderContract } from '../../generated-wrappers/forwarder';
-import { artifacts } from '../../src/artifacts';
-
-export class ForwarderWrapper {
- private readonly _web3Wrapper: Web3Wrapper;
- private readonly _forwarderContract: ForwarderContract;
- private readonly _logDecoder: LogDecoder;
- public static getPercentageOfValue(value: BigNumber, percentage: number): BigNumber {
- const numerator = constants.PERCENTAGE_DENOMINATOR.times(percentage).dividedToIntegerBy(100);
- const newValue = value.times(numerator).dividedToIntegerBy(constants.PERCENTAGE_DENOMINATOR);
- return newValue;
- }
- public static getWethForFeeOrders(feeAmount: BigNumber, feeOrders: SignedOrder[]): BigNumber {
- let wethAmount = new BigNumber(0);
- let remainingFeeAmount = feeAmount;
- _.forEach(feeOrders, feeOrder => {
- const feeAvailable = feeOrder.makerAssetAmount.minus(feeOrder.takerFee);
- if (!remainingFeeAmount.isZero() && feeAvailable.gt(remainingFeeAmount)) {
- wethAmount = wethAmount.plus(
- feeOrder.takerAssetAmount
- .times(remainingFeeAmount)
- .dividedBy(feeAvailable)
- .integerValue(BigNumber.ROUND_CEIL),
- );
- remainingFeeAmount = new BigNumber(0);
- } else if (!remainingFeeAmount.isZero()) {
- wethAmount = wethAmount.plus(feeOrder.takerAssetAmount);
- remainingFeeAmount = remainingFeeAmount.minus(feeAvailable);
- }
- });
- return wethAmount;
- }
- private static _createOptimizedOrders(signedOrders: SignedOrder[]): MarketSellOrders {
- _.forEach(signedOrders, (signedOrder, index) => {
- signedOrder.takerAssetData = constants.NULL_BYTES;
- if (index > 0) {
- signedOrder.makerAssetData = constants.NULL_BYTES;
- }
- });
- const params = formatters.createMarketSellOrders(signedOrders, constants.ZERO_AMOUNT);
- return params;
- }
- private static _createOptimizedZrxOrders(signedOrders: SignedOrder[]): MarketSellOrders {
- _.forEach(signedOrders, signedOrder => {
- signedOrder.makerAssetData = constants.NULL_BYTES;
- signedOrder.takerAssetData = constants.NULL_BYTES;
- });
- const params = formatters.createMarketSellOrders(signedOrders, constants.ZERO_AMOUNT);
- return params;
- }
- constructor(contractInstance: ForwarderContract, provider: Provider) {
- this._forwarderContract = contractInstance;
- this._web3Wrapper = new Web3Wrapper(provider);
- this._logDecoder = new LogDecoder(this._web3Wrapper, {
- ...artifacts,
- ...tokensArtifacts,
- ...protocolArtifacts,
- });
- }
- public async marketSellOrdersWithEthAsync(
- orders: SignedOrder[],
- feeOrders: SignedOrder[],
- txData: TxDataPayable,
- opts: { feePercentage?: BigNumber; feeRecipient?: string } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = ForwarderWrapper._createOptimizedOrders(orders);
- const feeParams = ForwarderWrapper._createOptimizedZrxOrders(feeOrders);
- const feePercentage = _.isUndefined(opts.feePercentage) ? constants.ZERO_AMOUNT : opts.feePercentage;
- const feeRecipient = _.isUndefined(opts.feeRecipient) ? constants.NULL_ADDRESS : opts.feeRecipient;
- const txHash = await this._forwarderContract.marketSellOrdersWithEth.sendTransactionAsync(
- params.orders,
- params.signatures,
- feeParams.orders,
- feeParams.signatures,
- feePercentage,
- feeRecipient,
- txData,
- );
- const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return tx;
- }
- public async marketBuyOrdersWithEthAsync(
- orders: SignedOrder[],
- feeOrders: SignedOrder[],
- makerAssetFillAmount: BigNumber,
- txData: TxDataPayable,
- opts: { feePercentage?: BigNumber; feeRecipient?: string } = {},
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const params = ForwarderWrapper._createOptimizedOrders(orders);
- const feeParams = ForwarderWrapper._createOptimizedZrxOrders(feeOrders);
- const feePercentage = _.isUndefined(opts.feePercentage) ? constants.ZERO_AMOUNT : opts.feePercentage;
- const feeRecipient = _.isUndefined(opts.feeRecipient) ? constants.NULL_ADDRESS : opts.feeRecipient;
- const txHash = await this._forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
- params.orders,
- makerAssetFillAmount,
- params.signatures,
- feeParams.orders,
- feeParams.signatures,
- feePercentage,
- feeRecipient,
- txData,
- );
- const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return tx;
- }
- public async withdrawAssetAsync(
- assetData: string,
- amount: BigNumber,
- txData: TxDataPayable,
- ): Promise<TransactionReceiptWithDecodedLogs> {
- const txHash = await this._forwarderContract.withdrawAsset.sendTransactionAsync(assetData, amount, txData);
- const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
- return tx;
- }
-}