fix: slippage inconsistency when recalculated in exchange proxy quote consumer (#412)
* fix: Pass slippage down rather than recalculate due to accuracy * CHANGELOG
This commit is contained in:
parent
0f701f42d3
commit
5d2cdb00c2
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "16.49.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fix `slippage` inconsistency when recalculated in exchange proxy quote consumer",
|
||||||
|
"pr": 412
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "16.49.2",
|
"version": "16.49.2",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -691,7 +691,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
|
|
||||||
function slipNonNativeOrders(quote: MarketSellSwapQuote | MarketBuySwapQuote): OptimizedMarketOrder[] {
|
function slipNonNativeOrders(quote: MarketSellSwapQuote | MarketBuySwapQuote): OptimizedMarketOrder[] {
|
||||||
const slippage = getMaxQuoteSlippageRate(quote);
|
const slippage = getMaxQuoteSlippageRate(quote);
|
||||||
if (!slippage) {
|
if (slippage === 0) {
|
||||||
return quote.orders;
|
return quote.orders;
|
||||||
}
|
}
|
||||||
return quote.orders.map(o => {
|
return quote.orders.map(o => {
|
||||||
@ -716,18 +716,5 @@ function slipNonNativeOrders(quote: MarketSellSwapQuote | MarketBuySwapQuote): O
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getMaxQuoteSlippageRate(quote: MarketBuySwapQuote | MarketSellSwapQuote): number {
|
function getMaxQuoteSlippageRate(quote: MarketBuySwapQuote | MarketSellSwapQuote): number {
|
||||||
if (quote.type === MarketOperation.Buy) {
|
return quote.worstCaseQuoteInfo.slippage;
|
||||||
// (worstCaseTaker - bestCaseTaker) / bestCaseTaker
|
|
||||||
// where worstCaseTaker >= bestCaseTaker
|
|
||||||
return quote.worstCaseQuoteInfo.takerAmount
|
|
||||||
.minus(quote.bestCaseQuoteInfo.takerAmount)
|
|
||||||
.div(quote.bestCaseQuoteInfo.takerAmount)
|
|
||||||
.toNumber();
|
|
||||||
}
|
|
||||||
// (bestCaseMaker - worstCaseMaker) / bestCaseMaker
|
|
||||||
// where bestCaseMaker >= worstCaseMaker
|
|
||||||
return quote.bestCaseQuoteInfo.makerAmount
|
|
||||||
.minus(quote.worstCaseQuoteInfo.makerAmount)
|
|
||||||
.div(quote.bestCaseQuoteInfo.makerAmount)
|
|
||||||
.toNumber();
|
|
||||||
}
|
}
|
||||||
|
@ -578,8 +578,8 @@ function calculateQuoteInfo(
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bestCaseQuoteInfo: fillResultsToQuoteInfo(bestCaseFillResult),
|
bestCaseQuoteInfo: fillResultsToQuoteInfo(bestCaseFillResult, 0),
|
||||||
worstCaseQuoteInfo: fillResultsToQuoteInfo(worstCaseFillResult),
|
worstCaseQuoteInfo: fillResultsToQuoteInfo(worstCaseFillResult, slippage),
|
||||||
sourceBreakdown: getSwapQuoteOrdersBreakdown(bestCaseFillResult.fillAmountBySource),
|
sourceBreakdown: getSwapQuoteOrdersBreakdown(bestCaseFillResult.fillAmountBySource),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -600,6 +600,7 @@ function calculateTwoHopQuoteInfo(
|
|||||||
}),
|
}),
|
||||||
).toNumber();
|
).toNumber();
|
||||||
const isSell = operation === MarketOperation.Sell;
|
const isSell = operation === MarketOperation.Sell;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bestCaseQuoteInfo: {
|
bestCaseQuoteInfo: {
|
||||||
makerAmount: isSell ? secondHopFill.output : secondHopFill.input,
|
makerAmount: isSell ? secondHopFill.output : secondHopFill.input,
|
||||||
@ -608,6 +609,7 @@ function calculateTwoHopQuoteInfo(
|
|||||||
feeTakerTokenAmount: constants.ZERO_AMOUNT,
|
feeTakerTokenAmount: constants.ZERO_AMOUNT,
|
||||||
protocolFeeInWeiAmount: constants.ZERO_AMOUNT,
|
protocolFeeInWeiAmount: constants.ZERO_AMOUNT,
|
||||||
gas,
|
gas,
|
||||||
|
slippage: 0,
|
||||||
},
|
},
|
||||||
// TODO jacob consolidate this with quote simulation worstCase
|
// TODO jacob consolidate this with quote simulation worstCase
|
||||||
worstCaseQuoteInfo: {
|
worstCaseQuoteInfo: {
|
||||||
@ -616,13 +618,14 @@ function calculateTwoHopQuoteInfo(
|
|||||||
: secondHopOrder.makerAmount,
|
: secondHopOrder.makerAmount,
|
||||||
takerAmount: isSell
|
takerAmount: isSell
|
||||||
? firstHopOrder.takerAmount
|
? firstHopOrder.takerAmount
|
||||||
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(),
|
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(BigNumber.ROUND_UP),
|
||||||
totalTakerAmount: isSell
|
totalTakerAmount: isSell
|
||||||
? firstHopOrder.takerAmount
|
? firstHopOrder.takerAmount
|
||||||
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(),
|
: firstHopOrder.takerAmount.times(1 + slippage).integerValue(BigNumber.ROUND_UP),
|
||||||
feeTakerTokenAmount: constants.ZERO_AMOUNT,
|
feeTakerTokenAmount: constants.ZERO_AMOUNT,
|
||||||
protocolFeeInWeiAmount: constants.ZERO_AMOUNT,
|
protocolFeeInWeiAmount: constants.ZERO_AMOUNT,
|
||||||
gas,
|
gas,
|
||||||
|
slippage,
|
||||||
},
|
},
|
||||||
sourceBreakdown: {
|
sourceBreakdown: {
|
||||||
[ERC20BridgeSource.MultiHop]: {
|
[ERC20BridgeSource.MultiHop]: {
|
||||||
@ -648,7 +651,7 @@ function getSwapQuoteOrdersBreakdown(fillAmountBySource: { [source: string]: Big
|
|||||||
return breakdown;
|
return breakdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillResultsToQuoteInfo(fr: QuoteFillResult): SwapQuoteInfo {
|
function fillResultsToQuoteInfo(fr: QuoteFillResult, slippage: number): SwapQuoteInfo {
|
||||||
return {
|
return {
|
||||||
makerAmount: fr.totalMakerAssetAmount,
|
makerAmount: fr.totalMakerAssetAmount,
|
||||||
takerAmount: fr.takerAssetAmount,
|
takerAmount: fr.takerAssetAmount,
|
||||||
@ -656,6 +659,7 @@ function fillResultsToQuoteInfo(fr: QuoteFillResult): SwapQuoteInfo {
|
|||||||
feeTakerTokenAmount: fr.takerFeeTakerAssetAmount,
|
feeTakerTokenAmount: fr.takerFeeTakerAssetAmount,
|
||||||
protocolFeeInWeiAmount: fr.protocolFeeAmount,
|
protocolFeeInWeiAmount: fr.protocolFeeAmount,
|
||||||
gas: fr.gas,
|
gas: fr.gas,
|
||||||
|
slippage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +208,7 @@ export type SwapQuote = MarketBuySwapQuote | MarketSellSwapQuote;
|
|||||||
* makerTokenAmount: The amount of makerAsset that will be acquired through the swap.
|
* makerTokenAmount: The amount of makerAsset that will be acquired through the swap.
|
||||||
* protocolFeeInWeiAmount: The amount of ETH to pay (in WEI) as protocol fee to perform the swap for desired asset.
|
* protocolFeeInWeiAmount: The amount of ETH to pay (in WEI) as protocol fee to perform the swap for desired asset.
|
||||||
* gas: Amount of estimated gas needed to fill the quote.
|
* gas: Amount of estimated gas needed to fill the quote.
|
||||||
|
* slippage: Amount of slippage to allow for.
|
||||||
*/
|
*/
|
||||||
export interface SwapQuoteInfo {
|
export interface SwapQuoteInfo {
|
||||||
feeTakerTokenAmount: BigNumber;
|
feeTakerTokenAmount: BigNumber;
|
||||||
@ -216,6 +217,7 @@ export interface SwapQuoteInfo {
|
|||||||
makerAmount: BigNumber;
|
makerAmount: BigNumber;
|
||||||
protocolFeeInWeiAmount: BigNumber;
|
protocolFeeInWeiAmount: BigNumber;
|
||||||
gas: number;
|
gas: number;
|
||||||
|
slippage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,6 +125,7 @@ describe('ExchangeProxySwapQuoteConsumer', () => {
|
|||||||
gas: Math.floor(Math.random() * 8e6),
|
gas: Math.floor(Math.random() * 8e6),
|
||||||
protocolFeeInWeiAmount: getRandomAmount(),
|
protocolFeeInWeiAmount: getRandomAmount(),
|
||||||
feeTakerTokenAmount: getRandomAmount(),
|
feeTakerTokenAmount: getRandomAmount(),
|
||||||
|
slippage: 0,
|
||||||
},
|
},
|
||||||
worstCaseQuoteInfo: {
|
worstCaseQuoteInfo: {
|
||||||
makerAmount: makerTokenFillAmount,
|
makerAmount: makerTokenFillAmount,
|
||||||
@ -133,6 +134,7 @@ describe('ExchangeProxySwapQuoteConsumer', () => {
|
|||||||
gas: Math.floor(Math.random() * 8e6),
|
gas: Math.floor(Math.random() * 8e6),
|
||||||
protocolFeeInWeiAmount: getRandomAmount(),
|
protocolFeeInWeiAmount: getRandomAmount(),
|
||||||
feeTakerTokenAmount: getRandomAmount(),
|
feeTakerTokenAmount: getRandomAmount(),
|
||||||
|
slippage: 0,
|
||||||
},
|
},
|
||||||
makerAmountPerEth: getRandomInteger(1, 1e9),
|
makerAmountPerEth: getRandomInteger(1, 1e9),
|
||||||
takerAmountPerEth: getRandomInteger(1, 1e9),
|
takerAmountPerEth: getRandomInteger(1, 1e9),
|
||||||
|
@ -24,6 +24,7 @@ export async function getFullyFillableSwapQuoteWithNoFeesAsync(
|
|||||||
totalTakerAmount: takerAmount,
|
totalTakerAmount: takerAmount,
|
||||||
protocolFeeInWeiAmount: protocolFeePerOrder.times(orders.length),
|
protocolFeeInWeiAmount: protocolFeePerOrder.times(orders.length),
|
||||||
gas: 200e3,
|
gas: 200e3,
|
||||||
|
slippage: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const breakdown = {
|
const breakdown = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user