From a65a78226592970cc21a877ffb30630d13994166 Mon Sep 17 00:00:00 2001 From: "Siyu Jiang (See-You John)" <91580504+jsy1218@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:18:51 -0700 Subject: [PATCH] chore: bump sor to 4.7.0 - feat: SOR level implementation to support 1) expanding mixed quoter v1 to L2s 2) support migrate mixed quoter v1 to mixed quoter v2 across chains (#746) * chore: bump sor to 4.7.0 - feat: SOR level implementation to support 1) expanding mixed quoter v1 to L2s 2) support migrate mixed quoter v1 to mixed quoter v2 across chains * 4.7.0 * also fix alpha-router integ-tests * make other gas params protocol dependent as well * fix alpha router compiling error --- package-lock.json | 4 +- package.json | 2 +- src/providers/on-chain-quote-provider.ts | 107 +++++++++--- src/routers/alpha-router/alpha-router.ts | 154 +++++++++++------- src/util/chains.ts | 8 +- .../alpha-router.integration.test.ts | 2 +- 6 files changed, 188 insertions(+), 89 deletions(-) diff --git a/package-lock.json b/package-lock.json index e58ad8b2e..7ec745915 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@uniswap/smart-order-router", - "version": "4.6.2", + "version": "4.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@uniswap/smart-order-router", - "version": "4.6.2", + "version": "4.7.0", "license": "GPL", "dependencies": { "@eth-optimism/sdk": "^3.2.2", diff --git a/package.json b/package.json index fa73e240b..869083a6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uniswap/smart-order-router", - "version": "4.6.2", + "version": "4.7.0", "description": "Uniswap Smart Order Router", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/src/providers/on-chain-quote-provider.ts b/src/providers/on-chain-quote-provider.ts index deb07b0f9..cc22ac8dc 100644 --- a/src/providers/on-chain-quote-provider.ts +++ b/src/providers/on-chain-quote-provider.ts @@ -349,23 +349,35 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { }, protected batchParams: ( optimisticCachedRoutes: boolean, - useMixedRouteQuoter: boolean - ) => BatchParams = (_optimisticCachedRoutes, _useMixedRouteQuoter) => { + protocol: Protocol + ) => BatchParams = (_optimisticCachedRoutes, _protocol) => { return { multicallChunk: 150, gasLimitPerCall: 1_000_000, quoteMinSuccessRate: 0.2, }; }, - protected gasErrorFailureOverride: FailureOverrides = { - gasLimitOverride: 1_500_000, - multicallChunk: 100, + protected gasErrorFailureOverride: ( + protocol: Protocol + ) => FailureOverrides = (_protocol: Protocol) => { + return { + gasLimitOverride: 1_500_000, + multicallChunk: 100, + }; }, // successRateFailureOverrides and blockNumberConfig are not always override in alpha-router. // So we will extract out below default values into constants. // In alpha-router default case, we will also define the constants with same values as below. - protected successRateFailureOverrides: FailureOverrides = DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, - protected blockNumberConfig: BlockNumberConfig = DEFAULT_BLOCK_NUMBER_CONFIGS, + protected successRateFailureOverrides: ( + protocol: Protocol + ) => FailureOverrides = (_protocol: Protocol) => { + return DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES; + }, + protected blockNumberConfig: (protocol: Protocol) => BlockNumberConfig = ( + _protocol: Protocol + ) => { + return DEFAULT_BLOCK_NUMBER_CONFIGS; + }, protected quoterAddressOverride?: ( useMixedRouteQuoter: boolean, mixedRouteContainsV4Pool: boolean, @@ -374,11 +386,21 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { protected metricsPrefix: ( chainId: ChainId, useMixedRouteQuoter: boolean, + mixedRouteContainsV4Pool: boolean, + protocol: Protocol, optimisticCachedRoutes: boolean - ) => string = (chainId, useMixedRouteQuoter, optimisticCachedRoutes) => + ) => string = ( + chainId, + useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, + optimisticCachedRoutes + ) => useMixedRouteQuoter - ? `ChainId_${chainId}_MixedQuoter_OptimisticCachedRoutes${optimisticCachedRoutes}_` - : `ChainId_${chainId}_V3Quoter_OptimisticCachedRoutes${optimisticCachedRoutes}_` + ? `ChainId_${chainId}_${protocol}RouteQuoter${ + mixedRouteContainsV4Pool ? 'V2' : 'V1' + }_OptimisticCachedRoutes${optimisticCachedRoutes}_` + : `ChainId_${chainId}_${protocol}Quoter_OptimisticCachedRoutes${optimisticCachedRoutes}_` ) {} private getQuoterAddress( @@ -611,6 +633,12 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { (route as MixedRoute).pools.some((pool) => pool instanceof V4Pool) ) : false; + const protocol = useMixedRouteQuoter + ? Protocol.MIXED + : useV4RouteQuoter + ? Protocol.V4 + : Protocol.V3; + const optimisticCachedRoutes = _providerConfig?.optimisticCachedRoutes ?? false; @@ -619,13 +647,13 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { let multicallChunk = this.batchParams( optimisticCachedRoutes, - useMixedRouteQuoter + protocol ).multicallChunk; let gasLimitOverride = this.batchParams( optimisticCachedRoutes, - useMixedRouteQuoter + protocol ).gasLimitPerCall; - const { baseBlockOffset, rollback } = this.blockNumberConfig; + const { baseBlockOffset, rollback } = this.blockNumberConfig(protocol); // Apply the base block offset if provided const originalBlockNumber = await this.provider.getBlockNumber(); @@ -707,6 +735,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteBatchSize`, inputs.length, @@ -716,6 +746,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteBatchSize_${ID_TO_NETWORK_NAME(this.chainId)}`, inputs.length, @@ -771,11 +803,6 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { try { totalCallsMade = totalCallsMade + 1; - const protocol = useMixedRouteQuoter - ? Protocol.MIXED - : useV4RouteQuoter - ? Protocol.V4 - : Protocol.V3; const results = await this.consolidateResults( protocol, useMixedRouteQuoter, @@ -790,6 +817,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { results.results, haveRetriedForSuccessRate, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes ); @@ -896,6 +925,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteBlockConflictErrorRetry`, 1, @@ -911,6 +942,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteBlockHeaderNotFoundRetry`, 1, @@ -955,6 +988,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteTimeoutRetry`, 1, @@ -968,6 +1003,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteOutOfGasExceptionRetry`, 1, @@ -975,8 +1012,10 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { ); haveRetriedForOutOfGas = true; } - gasLimitOverride = this.gasErrorFailureOverride.gasLimitOverride; - multicallChunk = this.gasErrorFailureOverride.multicallChunk; + gasLimitOverride = + this.gasErrorFailureOverride(protocol).gasLimitOverride; + multicallChunk = + this.gasErrorFailureOverride(protocol).multicallChunk; retryAll = true; } else if (error instanceof SuccessRateError) { if (!haveRetriedForSuccessRate) { @@ -984,6 +1023,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteSuccessRateRetry`, 1, @@ -993,9 +1034,9 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { // Low success rate can indicate too little gas given to each call. gasLimitOverride = - this.successRateFailureOverrides.gasLimitOverride; + this.successRateFailureOverrides(protocol).gasLimitOverride; multicallChunk = - this.successRateFailureOverrides.multicallChunk; + this.successRateFailureOverrides(protocol).multicallChunk; retryAll = true; } } else { @@ -1004,6 +1045,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteUnknownReasonRetry`, 1, @@ -1099,6 +1142,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteLatency`, endTime - startTime, @@ -1109,6 +1154,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteApproxGasUsedPerSuccessfulCall`, approxGasUsedPerSuccessCall, @@ -1119,6 +1166,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteNumRetryLoops`, finalAttemptNumber - 1, @@ -1129,6 +1178,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteTotalCallsToProvider`, totalCallsMade, @@ -1139,6 +1190,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteExpectedCallsToProvider`, expectedCallsMade, @@ -1149,6 +1202,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteNumRetriedCalls`, totalCallsMade - expectedCallsMade, @@ -1342,6 +1397,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { allResults: Result<[BigNumber, BigNumber[], number[], BigNumber]>[], haveRetriedForSuccessRate: boolean, useMixedRouteQuoter: boolean, + mixedRouteContainsV4Pool: boolean, + protocol: Protocol, optimisticCachedRoutes: boolean ): void | SuccessRateError { const numResults = allResults.length; @@ -1353,7 +1410,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { const { quoteMinSuccessRate } = this.batchParams( optimisticCachedRoutes, - useMixedRouteQuoter + protocol ); if (successRate < quoteMinSuccessRate) { if (haveRetriedForSuccessRate) { @@ -1364,6 +1421,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteRetriedSuccessRateLow`, successRate, @@ -1377,6 +1436,8 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider { `${this.metricsPrefix( this.chainId, useMixedRouteQuoter, + mixedRouteContainsV4Pool, + protocol, optimisticCachedRoutes )}QuoteSuccessRateLow`, successRate, diff --git a/src/routers/alpha-router/alpha-router.ts b/src/routers/alpha-router/alpha-router.ts index 358218498..713e1bbd1 100644 --- a/src/routers/alpha-router/alpha-router.ts +++ b/src/routers/alpha-router/alpha-router.ts @@ -95,6 +95,7 @@ import { Erc20__factory } from '../../types/other/factories/Erc20__factory'; import { getAddress, getAddressLowerCase, + MIXED_SUPPORTED, shouldWipeoutCachedRoutes, SWAP_ROUTER_02_ADDRESSES, V4_SUPPORTED, @@ -317,6 +318,11 @@ export type AlphaRouterParams = { */ v4Supported?: ChainId[]; + /** + * All the supported mixed chains configuration + */ + mixedSupported?: ChainId[]; + /** * The version of the universal router to use. */ @@ -536,6 +542,7 @@ export class AlphaRouter protected portionProvider: IPortionProvider; protected v2Supported?: ChainId[]; protected v4Supported?: ChainId[]; + protected mixedSupported?: ChainId[]; protected universalRouterVersion?: UniversalRouterVersion; constructor({ @@ -566,6 +573,7 @@ export class AlphaRouter portionProvider, v2Supported, v4Supported, + mixedSupported, universalRouterVersion, }: AlphaRouterParams) { this.chainId = chainId; @@ -613,21 +621,27 @@ export class AlphaRouter quoteMinSuccessRate: 0.1, }; }, - { - gasLimitOverride: 3_000_000, - multicallChunk: 45, + (_) => { + return { + gasLimitOverride: 3_000_000, + multicallChunk: 45, + }; }, - { - gasLimitOverride: 3_000_000, - multicallChunk: 45, + (_) => { + return { + gasLimitOverride: 3_000_000, + multicallChunk: 45, + }; }, - { - baseBlockOffset: -10, - rollback: { - enabled: true, - attemptsBeforeRollback: 1, - rollbackBlockOffset: -10, - }, + (_) => { + return { + baseBlockOffset: -10, + rollback: { + enabled: true, + attemptsBeforeRollback: 1, + rollbackBlockOffset: -10, + }, + }; } ); break; @@ -653,21 +667,27 @@ export class AlphaRouter quoteMinSuccessRate: 0.1, }; }, - { - gasLimitOverride: 3_000_000, - multicallChunk: 45, + (_) => { + return { + gasLimitOverride: 3_000_000, + multicallChunk: 45, + }; }, - { - gasLimitOverride: 3_000_000, - multicallChunk: 45, + (_) => { + return { + gasLimitOverride: 3_000_000, + multicallChunk: 45, + }; }, - { - baseBlockOffset: -10, - rollback: { - enabled: true, - attemptsBeforeRollback: 1, - rollbackBlockOffset: -10, - }, + (_) => { + return { + baseBlockOffset: -10, + rollback: { + enabled: true, + attemptsBeforeRollback: 1, + rollbackBlockOffset: -10, + }, + }; } ); break; @@ -688,21 +708,27 @@ export class AlphaRouter quoteMinSuccessRate: 0.1, }; }, - { - gasLimitOverride: 6_000_000, - multicallChunk: 13, + (_) => { + return { + gasLimitOverride: 6_000_000, + multicallChunk: 13, + }; }, - { - gasLimitOverride: 6_000_000, - multicallChunk: 13, + (_) => { + return { + gasLimitOverride: 6_000_000, + multicallChunk: 13, + }; }, - { - baseBlockOffset: -10, - rollback: { - enabled: true, - attemptsBeforeRollback: 1, - rollbackBlockOffset: -10, - }, + (_) => { + return { + baseBlockOffset: -10, + rollback: { + enabled: true, + attemptsBeforeRollback: 1, + rollbackBlockOffset: -10, + }, + }; } ); break; @@ -725,13 +751,17 @@ export class AlphaRouter quoteMinSuccessRate: 0.1, }; }, - { - gasLimitOverride: 30_000_000, - multicallChunk: 6, + (_) => { + return { + gasLimitOverride: 30_000_000, + multicallChunk: 6, + }; }, - { - gasLimitOverride: 30_000_000, - multicallChunk: 6, + (_) => { + return { + gasLimitOverride: 30_000_000, + multicallChunk: 6, + }; } ); break; @@ -753,13 +783,17 @@ export class AlphaRouter quoteMinSuccessRate: 0.1, }; }, - { - gasLimitOverride: 5_000_000, - multicallChunk: 5, + (_) => { + return { + gasLimitOverride: 5_000_000, + multicallChunk: 5, + }; }, - { - gasLimitOverride: 6_250_000, - multicallChunk: 4, + (_) => { + return { + gasLimitOverride: 6_250_000, + multicallChunk: 4, + }; } ); break; @@ -773,9 +807,9 @@ export class AlphaRouter this.multicall2Provider, RETRY_OPTIONS[chainId], (_) => BATCH_PARAMS[chainId]!, - GAS_ERROR_FAILURE_OVERRIDES[chainId], - SUCCESS_RATE_FAILURE_OVERRIDES[chainId], - BLOCK_NUMBER_CONFIGS[chainId] + (_) => GAS_ERROR_FAILURE_OVERRIDES[chainId]!, + (_) => SUCCESS_RATE_FAILURE_OVERRIDES[chainId]!, + (_) => BLOCK_NUMBER_CONFIGS[chainId]! ); break; default: @@ -785,9 +819,9 @@ export class AlphaRouter this.multicall2Provider, DEFAULT_RETRY_OPTIONS, (_) => DEFAULT_BATCH_PARAMS, - DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, - DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, - DEFAULT_BLOCK_NUMBER_CONFIGS + (_) => DEFAULT_GAS_ERROR_FAILURE_OVERRIDES, + (_) => DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES, + (_) => DEFAULT_BLOCK_NUMBER_CONFIGS ); break; } @@ -997,6 +1031,7 @@ export class AlphaRouter this.v2Supported = v2Supported ?? V2_SUPPORTED; this.v4Supported = v4Supported ?? V4_SUPPORTED; + this.mixedSupported = mixedSupported ?? MIXED_SUPPORTED; this.universalRouterVersion = universalRouterVersion ?? UniversalRouterVersion.V1_2; } @@ -2078,9 +2113,8 @@ export class AlphaRouter protocols.includes(Protocol.MIXED) || (noProtocolsSpecified && v2SupportedInChain && v4SupportedInChain); const mixedProtocolAllowed = - [ChainId.MAINNET, ChainId.SEPOLIA, ChainId.GOERLI].includes( - this.chainId - ) && tradeType === TradeType.EXACT_INPUT; + this.mixedSupported?.includes(this.chainId) && + tradeType === TradeType.EXACT_INPUT; const beforeGetCandidates = Date.now(); diff --git a/src/util/chains.ts b/src/util/chains.ts index c54f8cb1d..dd0e1badf 100644 --- a/src/util/chains.ts +++ b/src/util/chains.ts @@ -40,12 +40,16 @@ export const V2_SUPPORTED = [ ChainId.BASE, ChainId.BNB, ChainId.AVALANCHE, - ChainId.WORLDCHAIN, - ChainId.ASTROCHAIN_SEPOLIA, ]; export const V4_SUPPORTED = [ChainId.SEPOLIA]; +export const MIXED_SUPPORTED = [ + ChainId.MAINNET, + ChainId.SEPOLIA, + ChainId.GOERLI, +]; + export const HAS_L1_FEE = [ ChainId.OPTIMISM, ChainId.OPTIMISM_GOERLI, diff --git a/test/integ/routers/alpha-router/alpha-router.integration.test.ts b/test/integ/routers/alpha-router/alpha-router.integration.test.ts index ace156e94..fc330fc4d 100644 --- a/test/integ/routers/alpha-router/alpha-router.integration.test.ts +++ b/test/integ/routers/alpha-router/alpha-router.integration.test.ts @@ -132,7 +132,7 @@ const GAS_ESTIMATE_DEVIATION_PERCENT: { [chainId in ChainId]: number } = { [ChainId.MAINNET]: 50, [ChainId.GOERLI]: 62, [ChainId.SEPOLIA]: 75, - [ChainId.OPTIMISM]: 61, + [ChainId.OPTIMISM]: 71, [ChainId.OPTIMISM_GOERLI]: 30, [ChainId.OPTIMISM_SEPOLIA]: 30, [ChainId.ARBITRUM_ONE]: 53,