@0x/asset-swapper: respect max slippage in EP consumer
				
					
				
			This commit is contained in:
		@@ -129,6 +129,10 @@
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fix Balancer sampling",
 | 
			
		||||
                "pr": 2711
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Respect max slippage in EP consumer",
 | 
			
		||||
                "pr": 2712
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,8 @@ import { assert } from '../utils/assert';
 | 
			
		||||
import { ERC20BridgeSource, UniswapV2FillData } from '../utils/market_operation_utils/types';
 | 
			
		||||
import { getTokenFromAssetData } from '../utils/utils';
 | 
			
		||||
 | 
			
		||||
import { getMinBuyAmount } from './utils';
 | 
			
		||||
 | 
			
		||||
// tslint:disable-next-line:custom-no-magic-numbers
 | 
			
		||||
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
 | 
			
		||||
const { NULL_ADDRESS, ZERO_AMOUNT } = constants;
 | 
			
		||||
@@ -93,6 +95,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
        const sellToken = getTokenFromAssetData(quote.takerAssetData);
 | 
			
		||||
        const buyToken = getTokenFromAssetData(quote.makerAssetData);
 | 
			
		||||
        const sellAmount = quote.worstCaseQuoteInfo.totalTakerAssetAmount;
 | 
			
		||||
        const minBuyAmount = getMinBuyAmount(quote);
 | 
			
		||||
 | 
			
		||||
        // VIP routes.
 | 
			
		||||
        if (isDirectUniswapCompatible(quote, optsWithDefaults)) {
 | 
			
		||||
@@ -111,7 +114,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
                            return a;
 | 
			
		||||
                        }),
 | 
			
		||||
                        sellAmount,
 | 
			
		||||
                        quote.worstCaseQuoteInfo.makerAssetAmount,
 | 
			
		||||
                        minBuyAmount,
 | 
			
		||||
                        source === ERC20BridgeSource.SushiSwap,
 | 
			
		||||
                    )
 | 
			
		||||
                    .getABIEncodedTransactionData(),
 | 
			
		||||
@@ -225,7 +228,6 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
            }),
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        const minBuyAmount = BigNumber.max(0, quote.worstCaseQuoteInfo.makerAssetAmount.minus(buyTokenFeeAmount));
 | 
			
		||||
        const calldataHexString = this._exchangeProxy
 | 
			
		||||
            .transformERC20(
 | 
			
		||||
                isFromETH ? ETH_TOKEN_ADDRESS : sellToken,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								packages/asset-swapper/src/quote_consumers/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/asset-swapper/src/quote_consumers/utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { MarketOperation, SwapQuote } from '../types';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Compute the mminimum buy token amount for market operations by inferring
 | 
			
		||||
 * the slippage from the orders in a quote. We cannot rely on
 | 
			
		||||
 * `worstCaseQuoteInfo.makerAssetAmount` because that does not stop at
 | 
			
		||||
 * maximum slippage.
 | 
			
		||||
 */
 | 
			
		||||
export function getMinBuyAmount(quote: SwapQuote): BigNumber {
 | 
			
		||||
    // Infer the allowed maker asset slippage from the orders.
 | 
			
		||||
    const totalOrderMakerAssetAmount = BigNumber.sum(...quote.orders.map(o => o.makerAssetAmount));
 | 
			
		||||
    const totalFillMakerAssetAmount =
 | 
			
		||||
        quote.type === MarketOperation.Sell
 | 
			
		||||
            ? BigNumber.sum(...quote.orders.map(o => BigNumber.sum(0, ...o.fills.map(f => f.output))))
 | 
			
		||||
            : BigNumber.sum(...quote.orders.map(o => BigNumber.sum(0, ...o.fills.map(f => f.input))));
 | 
			
		||||
    if (totalFillMakerAssetAmount.eq(0)) {
 | 
			
		||||
        return quote.worstCaseQuoteInfo.makerAssetAmount;
 | 
			
		||||
    }
 | 
			
		||||
    if (totalOrderMakerAssetAmount.eq(totalFillMakerAssetAmount)) {
 | 
			
		||||
        // No slippage allowed on bought tokens.
 | 
			
		||||
        return quote.bestCaseQuoteInfo.makerAssetAmount;
 | 
			
		||||
    }
 | 
			
		||||
    const slipRatio = totalOrderMakerAssetAmount.div(totalFillMakerAssetAmount);
 | 
			
		||||
    return quote.bestCaseQuoteInfo.makerAssetAmount.times(slipRatio).integerValue(BigNumber.ROUND_DOWN);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user