feat: asset-swapper use ethToInputRate when ethToOutputRate is unavailable (#2660)
This commit is contained in:
parent
71cde281b9
commit
d0e9081852
@ -41,6 +41,10 @@
|
||||
{
|
||||
"note": "Fix depth buy scale",
|
||||
"pr": 2659
|
||||
},
|
||||
{
|
||||
"note": "Adjust fill by ethToInputRate when ethToOutputRate is 0",
|
||||
"pr": 2660
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -17,6 +17,7 @@ export function createFillPaths(opts: {
|
||||
dexQuotes?: DexSample[][];
|
||||
targetInput?: BigNumber;
|
||||
ethToOutputRate?: BigNumber;
|
||||
ethToInputRate?: BigNumber;
|
||||
excludedSources?: ERC20BridgeSource[];
|
||||
feeSchedule?: FeeSchedule;
|
||||
}): Fill[][] {
|
||||
@ -26,8 +27,9 @@ export function createFillPaths(opts: {
|
||||
const orders = opts.orders || [];
|
||||
const dexQuotes = opts.dexQuotes || [];
|
||||
const ethToOutputRate = opts.ethToOutputRate || ZERO_AMOUNT;
|
||||
const ethToInputRate = opts.ethToInputRate || ZERO_AMOUNT;
|
||||
// Create native fill paths.
|
||||
const nativePath = nativeOrdersToPath(side, orders, opts.targetInput, ethToOutputRate, feeSchedule);
|
||||
const nativePath = nativeOrdersToPath(side, orders, opts.targetInput, ethToOutputRate, ethToInputRate, feeSchedule);
|
||||
// Create DEX fill paths.
|
||||
const dexPaths = dexQuotesToPaths(side, dexQuotes, ethToOutputRate, feeSchedule);
|
||||
return filterPaths([...dexPaths, nativePath].map(p => clipPathToInput(p, opts.targetInput)), excludedSources);
|
||||
@ -54,6 +56,7 @@ function nativeOrdersToPath(
|
||||
orders: SignedOrderWithFillableAmounts[],
|
||||
targetInput: BigNumber = POSITIVE_INF,
|
||||
ethToOutputRate: BigNumber,
|
||||
ethToInputRate: BigNumber,
|
||||
fees: FeeSchedule,
|
||||
): Fill[] {
|
||||
const sourcePathId = hexUtils.random();
|
||||
@ -64,9 +67,10 @@ function nativeOrdersToPath(
|
||||
const takerAmount = fillableAmountsUtils.getTakerAssetAmountSwappedAfterOrderFees(order);
|
||||
const input = side === MarketOperation.Sell ? takerAmount : makerAmount;
|
||||
const output = side === MarketOperation.Sell ? makerAmount : takerAmount;
|
||||
const penalty = ethToOutputRate.times(
|
||||
fees[ERC20BridgeSource.Native] === undefined ? 0 : fees[ERC20BridgeSource.Native]!(),
|
||||
);
|
||||
const fee = fees[ERC20BridgeSource.Native] === undefined ? 0 : fees[ERC20BridgeSource.Native]!();
|
||||
const outputPenalty = !ethToOutputRate.isZero()
|
||||
? ethToOutputRate.times(fee)
|
||||
: ethToInputRate.times(fee).times(output.dividedToIntegerBy(input));
|
||||
// targetInput can be less than the order size
|
||||
// whilst the penalty is constant, it affects the adjusted output
|
||||
// only up until the target has been exhausted.
|
||||
@ -76,7 +80,7 @@ function nativeOrdersToPath(
|
||||
// scale the clipped output inline with the input
|
||||
const clippedOutput = clippedInput.dividedBy(input).times(output);
|
||||
const adjustedOutput =
|
||||
side === MarketOperation.Sell ? clippedOutput.minus(penalty) : clippedOutput.plus(penalty);
|
||||
side === MarketOperation.Sell ? clippedOutput.minus(outputPenalty) : clippedOutput.plus(outputPenalty);
|
||||
const adjustedRate =
|
||||
side === MarketOperation.Sell ? adjustedOutput.div(clippedInput) : clippedInput.div(adjustedOutput);
|
||||
// Skip orders with rates that are <= 0.
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ContractAddresses } from '@0x/contract-addresses';
|
||||
import { ZERO_AMOUNT } from '@0x/order-utils';
|
||||
import { RFQTIndicativeQuote } from '@0x/quote-server';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber, NULL_ADDRESS } from '@0x/utils';
|
||||
@ -114,6 +115,17 @@ export class MarketOperationUtils {
|
||||
this._liquidityProviderRegistry,
|
||||
this._multiBridge,
|
||||
),
|
||||
// Get ETH -> taker token price.
|
||||
await DexOrderSampler.ops.getMedianSellRateAsync(
|
||||
difference(FEE_QUOTE_SOURCES.concat(this._optionalSources()), _opts.excludedSources),
|
||||
takerToken,
|
||||
this._wethAddress,
|
||||
ONE_ETHER,
|
||||
this._wethAddress,
|
||||
this._sampler.balancerPoolsCache,
|
||||
this._liquidityProviderRegistry,
|
||||
this._multiBridge,
|
||||
),
|
||||
// Get sell quotes for taker -> maker.
|
||||
await DexOrderSampler.ops.getSellQuotesAsync(
|
||||
difference(
|
||||
@ -152,7 +164,7 @@ export class MarketOperationUtils {
|
||||
.then(async r => this._sampler.executeAsync(r));
|
||||
|
||||
const [
|
||||
[orderFillableAmounts, liquidityProviderAddress, ethToMakerAssetRate, dexQuotes],
|
||||
[orderFillableAmounts, liquidityProviderAddress, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes],
|
||||
rfqtIndicativeQuotes,
|
||||
[balancerQuotes],
|
||||
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
||||
@ -174,6 +186,7 @@ export class MarketOperationUtils {
|
||||
nativeOrders,
|
||||
orderFillableAmounts,
|
||||
ethToOutputRate: ethToMakerAssetRate,
|
||||
ethToInputRate: ethToTakerAssetRate,
|
||||
rfqtIndicativeQuotes,
|
||||
};
|
||||
}
|
||||
@ -207,6 +220,17 @@ export class MarketOperationUtils {
|
||||
makerToken,
|
||||
takerToken,
|
||||
),
|
||||
// Get ETH -> maker token price.
|
||||
await DexOrderSampler.ops.getMedianSellRateAsync(
|
||||
difference(FEE_QUOTE_SOURCES.concat(this._optionalSources()), _opts.excludedSources),
|
||||
makerToken,
|
||||
this._wethAddress,
|
||||
ONE_ETHER,
|
||||
this._wethAddress,
|
||||
this._sampler.balancerPoolsCache,
|
||||
this._liquidityProviderRegistry,
|
||||
this._multiBridge,
|
||||
),
|
||||
// Get ETH -> taker token price.
|
||||
await DexOrderSampler.ops.getMedianSellRateAsync(
|
||||
difference(FEE_QUOTE_SOURCES.concat(this._optionalSources()), _opts.excludedSources),
|
||||
@ -255,7 +279,7 @@ export class MarketOperationUtils {
|
||||
_opts,
|
||||
);
|
||||
const [
|
||||
[orderFillableAmounts, liquidityProviderAddress, ethToTakerAssetRate, dexQuotes],
|
||||
[orderFillableAmounts, liquidityProviderAddress, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes],
|
||||
rfqtIndicativeQuotes,
|
||||
[balancerQuotes],
|
||||
] = await Promise.all([samplerPromise, rfqtPromise, balancerPromise]);
|
||||
@ -276,6 +300,7 @@ export class MarketOperationUtils {
|
||||
nativeOrders,
|
||||
orderFillableAmounts,
|
||||
ethToOutputRate: ethToTakerAssetRate,
|
||||
ethToInputRate: ethToMakerAssetRate,
|
||||
rfqtIndicativeQuotes,
|
||||
};
|
||||
}
|
||||
@ -388,6 +413,7 @@ export class MarketOperationUtils {
|
||||
const batchOrderFillableAmounts = executeResults.splice(0, batchNativeOrders.length) as BigNumber[][];
|
||||
const batchEthToTakerAssetRate = executeResults.splice(0, batchNativeOrders.length) as BigNumber[];
|
||||
const batchDexQuotes = executeResults.splice(0, batchNativeOrders.length) as DexSample[][][];
|
||||
const ethToInputRate = ZERO_AMOUNT;
|
||||
|
||||
return Promise.all(
|
||||
batchNativeOrders.map(async (nativeOrders, i) => {
|
||||
@ -408,6 +434,7 @@ export class MarketOperationUtils {
|
||||
dexQuotes,
|
||||
inputAmount: makerAmount,
|
||||
ethToOutputRate: ethToTakerAssetRate,
|
||||
ethToInputRate,
|
||||
rfqtIndicativeQuotes: [],
|
||||
inputToken: makerToken,
|
||||
outputToken: takerToken,
|
||||
@ -454,6 +481,7 @@ export class MarketOperationUtils {
|
||||
rfqtIndicativeQuotes,
|
||||
dexQuotes,
|
||||
ethToOutputRate,
|
||||
ethToInputRate,
|
||||
} = marketSideLiquidity;
|
||||
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
|
||||
// Convert native orders and dex quotes into fill paths.
|
||||
@ -467,6 +495,7 @@ export class MarketOperationUtils {
|
||||
dexQuotes,
|
||||
targetInput: inputAmount,
|
||||
ethToOutputRate,
|
||||
ethToInputRate,
|
||||
excludedSources: opts.excludedSources,
|
||||
feeSchedule: opts.feeSchedule,
|
||||
});
|
||||
|
@ -291,5 +291,6 @@ export interface MarketSideLiquidity {
|
||||
nativeOrders: SignedOrder[];
|
||||
orderFillableAmounts: BigNumber[];
|
||||
ethToOutputRate: BigNumber;
|
||||
ethToInputRate: BigNumber;
|
||||
rfqtIndicativeQuotes: RFQTIndicativeQuote[];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user