diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index d57014b38b..7d81bf5dbb 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "16.49.9", + "changes": [ + { + "note": "Fix native order scaling & filter out 1 wei quotes", + "pr": "430" + } + ] + }, { "timestamp": 1645569128, "version": "16.49.8", diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index 1792a65932..209d956b3a 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -66,7 +66,7 @@ "@0x/contracts-zero-ex": "^0.31.0", "@0x/dev-utils": "^4.2.11", "@0x/json-schemas": "^6.4.1", - "@0x/neon-router": "^0.3.2", + "@0x/neon-router": "^0.3.3", "@0x/protocol-utils": "^1.11.0", "@0x/quote-server": "^6.0.6", "@0x/types": "^3.3.4", diff --git a/packages/asset-swapper/src/utils/market_operation_utils/path_optimizer.ts b/packages/asset-swapper/src/utils/market_operation_utils/path_optimizer.ts index 1b7a85ba3c..14d1d6e251 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/path_optimizer.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/path_optimizer.ts @@ -21,6 +21,8 @@ const MIN_NUM_SAMPLE_INPUTS = 3; const isDexSample = (obj: DexSample | NativeOrderWithFillableAmounts): obj is DexSample => !!(obj as DexSample).source; +const ONE_BASE_UNIT = new BigNumber(1); + function nativeOrderToNormalizedAmounts( side: MarketOperation, nativeOrder: NativeOrderWithFillableAmounts, @@ -75,6 +77,13 @@ function findRoutesAndCreateOptimalPath( fees: FeeSchedule, neonRouterNumSamples: number, ): Path | undefined { + // Currently the rust router is unable to handle 1 base unit sized quotes and will error out + // To avoid flooding the logs with these errors we just return an insufficient liquidity error + // which is how the JS router handles these quotes today + if (input.eq(ONE_BASE_UNIT)) { + return undefined; + } + const createFill = (sample: DexSample): Fill | undefined => { const fills = dexSamplesToFills(side, [sample], opts.outputAmountPerEth, opts.inputAmountPerEth, fees); // NOTE: If the sample has 0 output dexSamplesToFills will return [] because no fill can be created @@ -155,12 +164,24 @@ function findRoutesAndCreateOptimalPath( const inputs = []; const outputs = []; const outputFees = []; - // NOTE: We start at 0 here because the native order might be much larger than the amount - // By starting at 0 we make sure we can always use a portion of the native order to fill/partial fill - for (let i = 0; i <= 12; i++) { - const fraction = i / 12; - const currentInput = BigNumber.min(normalizedOrderInput.times(fraction), normalizedOrderInput); - const currentOutput = BigNumber.min(normalizedOrderOutput.times(fraction), normalizedOrderOutput); + + // NOTE: Limit orders can be both larger or smaller than the input amount + // If the order is larger than the input we can scale the order to the size of + // the quote input (order pricing is constant) and then create 13 "samples" up to + // and including the full quote input amount. + // If the order is smaller we don't need to scale anything, we will just end up + // with trailing duplicate samples for the order input as we cannot go higher + const scaleToInput = BigNumber.min(input.dividedBy(normalizedOrderInput), 1); + for (let i = 1; i <= 13; i++) { + const fraction = i / 13; + const currentInput = BigNumber.min( + normalizedOrderInput.times(scaleToInput).times(fraction), + normalizedOrderInput, + ); + const currentOutput = BigNumber.min( + normalizedOrderOutput.times(scaleToInput).times(fraction), + normalizedOrderOutput, + ); const id = `${ERC20BridgeSource.Native}-${serializedPaths.length}-${idx}-${i}`; inputs.push(currentInput.integerValue().toNumber()); outputs.push(currentOutput.integerValue().toNumber()); diff --git a/yarn.lock b/yarn.lock index d93094ab7b..b78fa83920 100644 --- a/yarn.lock +++ b/yarn.lock @@ -959,10 +959,10 @@ typedoc "~0.16.11" yargs "^10.0.3" -"@0x/neon-router@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@0x/neon-router/-/neon-router-0.3.2.tgz#dc68d0a108060d607b48e3d32ce0ff46f8dc0cc2" - integrity sha512-AdSPeCxRcjdpmWDkJI1wg+X4q14tmLE21vM0AixtMQQI5+f22sIeUCrPqU9FFKqMQTOW0/3d8tVXzxdollahbA== +"@0x/neon-router@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@0x/neon-router/-/neon-router-0.3.3.tgz#dab540f4cd2aea6441ba29cbc35c28ca3f7a2b4f" + integrity sha512-xRIpRJ+gStLfDQI9mVdeugoLHQAp/bZfX7dycEQdStZlF6kcZk5kRe/iXCFoxoEY42fMaQW0/7JMFiB1C18t6Q== dependencies: "@mapbox/node-pre-gyp" "^1.0.5"