diff options
Diffstat (limited to 'packages/contracts/test')
6 files changed, 137 insertions, 77 deletions
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index 440097562..46b3569bd 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -69,13 +69,22 @@ describe('matchOrders', () => { 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, - feeRecipientAddressRight, + // tslint:disable-next-line:trailing-comma + feeRecipientAddressRight ] = _.slice(accounts, 0, 6)); // Create wrappers erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); @@ -201,9 +210,11 @@ describe('matchOrders', () => { // Match signedOrderLeft with signedOrderRight let newERC20BalancesByOwner: ERC20BalancesByOwner; let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner; + // prettier-ignore [ newERC20BalancesByOwner, - newERC721TokenIdsByOwner, + // tslint:disable-next-line:trailing-comma + newERC721TokenIdsByOwner ] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync( signedOrderLeft, signedOrderRight, @@ -306,9 +317,11 @@ describe('matchOrders', () => { // Match orders let newERC20BalancesByOwner: ERC20BalancesByOwner; let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner; + // prettier-ignore [ newERC20BalancesByOwner, - newERC721TokenIdsByOwner, + // tslint:disable-next-line:trailing-comma + newERC721TokenIdsByOwner ] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync( signedOrderLeft, signedOrderRight, @@ -374,9 +387,11 @@ describe('matchOrders', () => { // Match orders let newERC20BalancesByOwner: ERC20BalancesByOwner; let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner; + // prettier-ignore [ newERC20BalancesByOwner, - newERC721TokenIdsByOwner, + // tslint:disable-next-line:trailing-comma + newERC721TokenIdsByOwner ] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync( signedOrderLeft, signedOrderRight, diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index d5e522220..7bac2bdef 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -1,6 +1,6 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { signatureUtils, assetDataUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils'; -import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types'; +import { signatureUtils, assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; +import { RevertReason, SignatureType, SignedOrder, SignerType } from '@0xproject/types'; import * as chai from 'chai'; import { LogWithDecodedArgs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); @@ -113,7 +113,7 @@ describe('MixinSignatureValidator', () => { it('should revert when signature type is unsupported', async () => { const unsupportedSignatureType = SignatureType.NSignatureTypes; - const unsupportedSignatureHex = `0x${unsupportedSignatureType}`; + const unsupportedSignatureHex = '0x' + Buffer.from([unsupportedSignatureType]).toString('hex'); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); return expectContractCallFailed( signatureValidator.publicIsValidSignature.callAsync( @@ -126,7 +126,7 @@ describe('MixinSignatureValidator', () => { }); it('should revert when SignatureType=Illegal', async () => { - const unsupportedSignatureHex = `0x${SignatureType.Illegal}`; + const unsupportedSignatureHex = '0x' + Buffer.from([SignatureType.Illegal]).toString('hex'); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); return expectContractCallFailed( signatureValidator.publicIsValidSignature.callAsync( @@ -139,7 +139,7 @@ describe('MixinSignatureValidator', () => { }); it('should return false when SignatureType=Invalid and signature has a length of zero', async () => { - const signatureHex = `0x${SignatureType.Invalid}`; + const signatureHex = '0x' + Buffer.from([SignatureType.Invalid]).toString('hex'); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync( orderHashHex, @@ -215,7 +215,7 @@ describe('MixinSignatureValidator', () => { const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix( orderHashHex, - MessagePrefixType.EthSign, + SignerType.Default, ); const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex); const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey); @@ -241,7 +241,7 @@ describe('MixinSignatureValidator', () => { const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix( orderHashHex, - MessagePrefixType.EthSign, + SignerType.Default, ); const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex); const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey); @@ -391,10 +391,7 @@ describe('MixinSignatureValidator', () => { it('should return true when SignatureType=Trezor and signature is valid', async () => { // Create Trezor signature const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix( - orderHashHex, - MessagePrefixType.Trezor, - ); + const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex, SignerType.Trezor); const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex); const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey); // Create 0x signature from Trezor signature @@ -417,10 +414,7 @@ describe('MixinSignatureValidator', () => { it('should return false when SignatureType=Trezor and signature is invalid', async () => { // Create Trezor signature const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix( - orderHashHex, - MessagePrefixType.Trezor, - ); + const orderHashWithTrezorPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex, SignerType.Trezor); const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex); const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey); // Create 0x signature from Trezor signature diff --git a/packages/contracts/test/forwarder/forwarder.ts b/packages/contracts/test/forwarder/forwarder.ts index 19639d3aa..28ffdeabe 100644 --- a/packages/contracts/test/forwarder/forwarder.ts +++ b/packages/contracts/test/forwarder/forwarder.ts @@ -36,6 +36,7 @@ describe(ContractName.Forwarder, () => { let feeRecipientAddress: string; let otherAddress: string; let defaultMakerAssetAddress: string; + let zrxAssetData: string; let weth: DummyERC20TokenContract; let zrxToken: DummyERC20TokenContract; @@ -90,7 +91,7 @@ describe(ContractName.Forwarder, () => { erc20Wrapper.addDummyTokenContract(weth); const wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address); - const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); + zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync( artifacts.Exchange, provider, @@ -722,25 +723,18 @@ describe(ContractName.Forwarder, () => { ); expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT); }); - it('should not change balances if the amount of ETH sent is too low to fill the makerAssetAmount', async () => { + 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); - - 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 totalEthSpent = gasPrice.times(tx.gasUsed); - - expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent)); - expect(newBalances).to.deep.equal(erc20Balances); - expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT); + 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]; @@ -775,7 +769,7 @@ describe(ContractName.Forwarder, () => { ); expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT); }); - it('should buy an ERC721 asset and ignore later orders with different makerAssetData', async () => { + 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), @@ -786,33 +780,12 @@ describe(ContractName.Forwarder, () => { const feeOrders: SignedOrder[] = []; const makerAssetFillAmount = new BigNumber(1).plus(differentMakerAssetDataOrder.makerAssetAmount); 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); - expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[makerAddress][defaultMakerAssetAddress], - ); - expect(newBalances[takerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[takerAddress][defaultMakerAssetAddress], + 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 () => { @@ -998,6 +971,26 @@ describe(ContractName.Forwarder, () => { ); }); }); + 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/packages/contracts/test/utils/exchange_wrapper.ts b/packages/contracts/test/utils/exchange_wrapper.ts index 490ea959b..d57592d6d 100644 --- a/packages/contracts/test/utils/exchange_wrapper.ts +++ b/packages/contracts/test/utils/exchange_wrapper.ts @@ -8,7 +8,7 @@ import { ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { formatters } from './formatters'; import { LogDecoder } from './log_decoder'; import { orderUtils } from './order_utils'; -import { OrderInfo, SignedTransaction } from './types'; +import { FillResults, OrderInfo, SignedTransaction } from './types'; export class ExchangeWrapper { private readonly _exchange: ExchangeContract; @@ -243,4 +243,27 @@ export class ExchangeWrapper { const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); return tx; } + 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; + } } diff --git a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts index bdd1e62a2..284c4a2db 100644 --- a/packages/contracts/test/utils/fill_order_combinatorial_utils.ts +++ b/packages/contracts/test/utils/fill_order_combinatorial_utils.ts @@ -15,6 +15,7 @@ import * as _ from 'lodash'; import 'make-promises-safe'; import { ExchangeContract, ExchangeFillEventArgs } from '../../generated_contract_wrappers/exchange'; +import { TestLibsContract } from '../../generated_contract_wrappers/test_libs'; import { artifacts } from './artifacts'; import { expectTransactionFailedAsync } from './assertions'; @@ -123,6 +124,8 @@ export async function fillOrderCombinatorialUtilsFactoryAsync( exchangeContract.address, ); + const testLibsContract = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults); + const fillOrderCombinatorialUtils = new FillOrderCombinatorialUtils( orderFactory, ownerAddress, @@ -132,6 +135,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync( zrxAssetData, exchangeWrapper, assetWrapper, + testLibsContract, ); return fillOrderCombinatorialUtils; } @@ -145,6 +149,7 @@ export class FillOrderCombinatorialUtils { public zrxAssetData: string; public exchangeWrapper: ExchangeWrapper; public assetWrapper: AssetWrapper; + public testLibsContract: TestLibsContract; public static generateFillOrderCombinations(): FillScenario[] { const takerScenarios = [ TakerScenario.Unspecified, @@ -329,6 +334,7 @@ export class FillOrderCombinatorialUtils { zrxAssetData: string, exchangeWrapper: ExchangeWrapper, assetWrapper: AssetWrapper, + testLibsContract: TestLibsContract, ) { this.orderFactory = orderFactory; this.ownerAddress = ownerAddress; @@ -338,6 +344,7 @@ export class FillOrderCombinatorialUtils { this.zrxAssetData = zrxAssetData; this.exchangeWrapper = exchangeWrapper; this.assetWrapper = assetWrapper; + this.testLibsContract = testLibsContract; } public async testFillOrderScenarioAsync( provider: Provider, @@ -410,6 +417,8 @@ export class FillOrderCombinatorialUtils { lazyStore, fillRevertReasonIfExists, ); + + await this._abiEncodeFillOrderAndAssertOutcomeAsync(signedOrder, takerAssetFillAmount); } private async _fillOrderAndAssertOutcomeAsync( signedOrder: SignedOrder, @@ -456,6 +465,29 @@ export class FillOrderCombinatorialUtils { signedOrder.takerAssetAmount, signedOrder.makerAssetAmount, ); + const expMakerFeePaid = orderUtils.getPartialAmount( + expFilledTakerAmount, + signedOrder.takerAssetAmount, + signedOrder.makerFee, + ); + const expTakerFeePaid = orderUtils.getPartialAmount( + expFilledTakerAmount, + signedOrder.takerAssetAmount, + signedOrder.takerFee, + ); + const fillResults = await this.exchangeWrapper.getFillOrderResultsAsync(signedOrder, this.takerAddress, { + takerAssetFillAmount, + }); + expect(fillResults.takerAssetFilledAmount).to.be.bignumber.equal( + expFilledTakerAmount, + 'takerAssetFilledAmount', + ); + expect(fillResults.makerAssetFilledAmount).to.be.bignumber.equal( + expFilledMakerAmount, + 'makerAssetFilledAmount', + ); + expect(fillResults.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'takerFeePaid'); + expect(fillResults.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'makerFeePaid'); // - Let's fill the order! const txReceipt = await this.exchangeWrapper.fillOrderAsync(signedOrder, this.takerAddress, { @@ -479,17 +511,7 @@ export class FillOrderCombinatorialUtils { expFilledTakerAmount, 'log.args.takerAssetFilledAmount', ); - const expMakerFeePaid = orderUtils.getPartialAmount( - expFilledTakerAmount, - signedOrder.takerAssetAmount, - signedOrder.makerFee, - ); expect(log.args.makerFeePaid).to.be.bignumber.equal(expMakerFeePaid, 'log.args.makerFeePaid'); - const expTakerFeePaid = orderUtils.getPartialAmount( - expFilledTakerAmount, - signedOrder.takerAssetAmount, - signedOrder.takerFee, - ); expect(log.args.takerFeePaid).to.be.bignumber.equal(expTakerFeePaid, 'logs.args.takerFeePaid'); expect(log.args.orderHash).to.be.equal(orderHash, 'log.args.orderHash'); expect(log.args.makerAssetData).to.be.equal(makerAssetData, 'log.args.makerAssetData'); @@ -571,6 +593,19 @@ export class FillOrderCombinatorialUtils { 'ZRXAssetBalanceOfFeeRecipient', ); } + private async _abiEncodeFillOrderAndAssertOutcomeAsync( + signedOrder: SignedOrder, + takerAssetFillAmount: BigNumber, + ): Promise<void> { + const params = orderUtils.createFill(signedOrder, takerAssetFillAmount); + const expectedAbiEncodedData = this.exchangeWrapper.abiEncodeFillOrder(signedOrder, { takerAssetFillAmount }); + const libsAbiEncodedData = await this.testLibsContract.publicAbiEncodeFillOrder.callAsync( + params.order, + params.takerAssetFillAmount, + params.signature, + ); + expect(libsAbiEncodedData).to.be.equal(expectedAbiEncodedData, 'ABIEncodedFillOrderData'); + } private async _getTakerAssetFillAmountAsync( signedOrder: SignedOrder, takerAssetFillAmountScenario: TakerAssetFillAmountScenario, diff --git a/packages/contracts/test/utils/forwarder_wrapper.ts b/packages/contracts/test/utils/forwarder_wrapper.ts index ef7476e36..5b9a63ddf 100644 --- a/packages/contracts/test/utils/forwarder_wrapper.ts +++ b/packages/contracts/test/utils/forwarder_wrapper.ts @@ -106,12 +106,12 @@ export class ForwarderWrapper { const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); return tx; } - public async withdrawERC20Async( - tokenAddress: string, + public async withdrawAssetAsync( + assetData: string, amount: BigNumber, txData: TxDataPayable, ): Promise<TransactionReceiptWithDecodedLogs> { - const txHash = await this._forwarderContract.withdrawERC20.sendTransactionAsync(tokenAddress, amount, txData); + const txHash = await this._forwarderContract.withdrawAsset.sendTransactionAsync(assetData, amount, txData); const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); return tx; } |