diff --git a/packages/asset-swapper/src/quote_consumers/utils.ts b/packages/asset-swapper/src/quote_consumers/utils.ts index c805e79939..9f5d40b871 100644 --- a/packages/asset-swapper/src/quote_consumers/utils.ts +++ b/packages/asset-swapper/src/quote_consumers/utils.ts @@ -1,9 +1,9 @@ import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; +import { constants } from '../constants'; import { MarketOperation, SwapQuote } from '../types'; import { ERC20BridgeSource } from '../utils/market_operation_utils/types'; -import { constants } from '../constants'; const { ZERO_AMOUNT } = constants; @@ -19,6 +19,7 @@ export function getSwapMinBuyAmount(quote: SwapQuote): BigNumber { } // Infer the allowed maker asset slippage from the orders. const totalOrderMakerAssetAmount = BigNumber.sum(...quote.orders.map(o => o.fillableMakerAssetAmount)); + // tslint:disable: prefer-conditional-expression let totalFillMakerAssetAmount = ZERO_AMOUNT; for (const o of quote.orders) { if (o.fills.length === 0 || o.fills[0].source === ERC20BridgeSource.Native) { @@ -28,11 +29,11 @@ export function getSwapMinBuyAmount(quote: SwapQuote): BigNumber { totalFillMakerAssetAmount = totalFillMakerAssetAmount.plus(BigNumber.sum(...o.fills.map(f => f.output))); } } + // tslint:enable: prefer-conditional-expression if (totalOrderMakerAssetAmount.eq(totalFillMakerAssetAmount)) { // No slippage allowed across all orders. return quote.bestCaseQuoteInfo.makerAssetAmount; } const slipRatio = totalOrderMakerAssetAmount.div(totalFillMakerAssetAmount); - console.log(slipRatio); return quote.bestCaseQuoteInfo.makerAssetAmount.times(slipRatio).integerValue(BigNumber.ROUND_DOWN); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index 804dcfa3a6..efcb699a7a 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -291,7 +291,7 @@ function createBridgeOrder( makerAssetData = assetDataUtils.encodeERC20BridgeAssetData( makerToken, bridgeAddress, - createBalancerBridgeData(takerToken, makerToken), + createBalancerBridgeData(takerToken, balancerFillData.poolAddress), ); break; case ERC20BridgeSource.Bancor: diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index 62bcaeba2b..9ef979049c 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -798,9 +798,8 @@ export class SamplerOperations { liquidityProviderRegistryAddress?: string, multiBridgeAddress?: string, ): BatchedOperation { - const _sources = BATCH_SOURCE_FILTERS.getAllowed(sources); const subOps = this._getSellQuoteOperations( - _sources, + sources, makerToken, takerToken, takerFillAmounts, @@ -839,9 +838,8 @@ export class SamplerOperations { wethAddress: string, liquidityProviderRegistryAddress?: string, ): BatchedOperation { - const _sources = BATCH_SOURCE_FILTERS.getAllowed(sources); const subOps = this._getBuyQuoteOperations( - _sources, + sources, makerToken, takerToken, makerFillAmounts, @@ -880,8 +878,13 @@ export class SamplerOperations { liquidityProviderRegistryAddress?: string, multiBridgeAddress?: string, ): SourceQuoteOperation[] { + const _sources = BATCH_SOURCE_FILTERS.exclude( + liquidityProviderRegistryAddress ? [] : [ERC20BridgeSource.LiquidityProvider], + ) + .exclude(multiBridgeAddress ? [] : [ERC20BridgeSource.MultiBridge]) + .getAllowed(sources); return _.flatten( - sources.map( + _sources.map( (source): SourceQuoteOperation | SourceQuoteOperation[] => { switch (source) { case ERC20BridgeSource.Eth2Dai: @@ -984,8 +987,11 @@ export class SamplerOperations { wethAddress: string, liquidityProviderRegistryAddress?: string, ): SourceQuoteOperation[] { + const _sources = BATCH_SOURCE_FILTERS.exclude( + liquidityProviderRegistryAddress ? [] : [ERC20BridgeSource.LiquidityProvider], + ).getAllowed(sources); return _.flatten( - sources.map( + _sources.map( (source): SourceQuoteOperation | SourceQuoteOperation[] => { switch (source) { case ERC20BridgeSource.Eth2Dai: diff --git a/packages/asset-swapper/src/utils/quote_simulation.ts b/packages/asset-swapper/src/utils/quote_simulation.ts index 2e0b2240bb..5e46046e79 100644 --- a/packages/asset-swapper/src/utils/quote_simulation.ts +++ b/packages/asset-swapper/src/utils/quote_simulation.ts @@ -3,7 +3,7 @@ import { BigNumber } from '@0x/utils'; import { constants } from '../constants'; import { MarketOperation } from '../types'; -import { CollapsedFill, FeeSchedule, OptimizedMarketOrder } from './market_operation_utils/types'; +import { CollapsedFill, ERC20BridgeSource, FeeSchedule, OptimizedMarketOrder } from './market_operation_utils/types'; import { isOrderTakerFeePayableWithMakerAsset, isOrderTakerFeePayableWithTakerAsset } from './utils'; const { PROTOCOL_FEE_MULTIPLIER, ZERO_AMOUNT } = constants; @@ -261,16 +261,27 @@ function createWorstCaseFillOrderCalls(quoteInfo: QuoteFillInfo): QuoteFillOrder // Apply order slippage to its fill paths. function getSlippedOrderFills(order: OptimizedMarketOrder, side: MarketOperation): CollapsedFill[] { - const totalInput = BigNumber.sum(...order.fills.map(f => f.input)); - const totalOutput = BigNumber.sum(...order.fills.map(f => f.output)); - const inputScaling = - side === MarketOperation.Sell - ? order.fillableTakerAssetAmount.div(totalInput) - : order.fillableMakerAssetAmount.div(totalInput); - const outputScaling = - side === MarketOperation.Sell - ? order.fillableMakerAssetAmount.div(totalOutput) - : order.fillableTakerAssetAmount.div(totalOutput); + // Infer the slippage from the order amounts vs fill amounts. + let inputScaling: BigNumber; + let outputScaling: BigNumber; + const source = order.fills[0].source; + if (source === ERC20BridgeSource.Native) { + // Native orders do not have slippage applied to them. + inputScaling = new BigNumber(1); + outputScaling = new BigNumber(1); + } else { + if (side === MarketOperation.Sell) { + const totalFillableTakerAssetAmount = BigNumber.sum(...order.fills.map(f => f.input)); + const totalFillableMakerAssetAmount = BigNumber.sum(...order.fills.map(f => f.output)); + inputScaling = order.fillableTakerAssetAmount.div(totalFillableTakerAssetAmount); + outputScaling = order.fillableMakerAssetAmount.div(totalFillableMakerAssetAmount); + } else { + const totalFillableTakerAssetAmount = BigNumber.sum(...order.fills.map(f => f.output)); + const totalFillableMakerAssetAmount = BigNumber.sum(...order.fills.map(f => f.input)); + inputScaling = order.fillableMakerAssetAmount.div(totalFillableMakerAssetAmount); + outputScaling = order.fillableTakerAssetAmount.div(totalFillableTakerAssetAmount); + } + } return order.fills.map(f => ({ ...f, input: f.input.times(inputScaling), diff --git a/packages/asset-swapper/test/quote_simulation_test.ts b/packages/asset-swapper/test/quote_simulation_test.ts index 07493b47d6..ae106b30df 100644 --- a/packages/asset-swapper/test/quote_simulation_test.ts +++ b/packages/asset-swapper/test/quote_simulation_test.ts @@ -22,7 +22,7 @@ describe('quote_simulation tests', async () => { const TAKER_TOKEN = randomAddress(); const DEFAULT_MAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(MAKER_TOKEN); const DEFAULT_TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN); - const GAS_SCHEDULE = { [ERC20BridgeSource.Native]: _.constant(1) }; + const GAS_SCHEDULE = { [ERC20BridgeSource.Uniswap]: _.constant(1) }; // Check if two numbers are within `maxError` error rate within each other. function assertRoughlyEquals(n1: BigNumber, n2: BigNumber, maxError: BigNumber | number = 1e-10): void { @@ -164,7 +164,7 @@ describe('quote_simulation tests', async () => { const subFillOutputs = subdivideAmount(outputs[i], count); return { sourcePathId: nativeSourcePathId, - source: ERC20BridgeSource.Native, + source: ERC20BridgeSource.Uniswap, input: inputs[i], output: outputs[i], subFills: _.times(count, j => ({