Skip to content

Commit

Permalink
feat: support routing-api to shadow request quoter v2 on Polygon Mumb…
Browse files Browse the repository at this point in the history
…ai and Sepolia (Uniswap#510)

* new polygon and mainnet v3 quoter address

* integ-test fork after quoter v2 deploy block

* update the fork block to avoid invalid nonce

* add metrics to prep for shadow on-chain quote provider

* remove new quoter addresses so that they can be passed in as overrides

* add polygon specific override

* define default as shared static readonly variables

* don't use static readonly variables

* remove the metrics prefix underscore as it discontinues the existing onchain quoter metrics

* add comments explaining the rationale behind which default quote params are defined as constants and which params are not

* add on-chain quotes return type, so as to be used in routing-api

* change to polygon mumbai and sepolia deployed quoter address
  • Loading branch information
jsy1218 authored Apr 12, 2024
1 parent 2a61d3b commit dfa0357
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 60 deletions.
92 changes: 49 additions & 43 deletions src/providers/on-chain-quote-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import {
} from '../util/addresses';
import { CurrencyAmount } from '../util/amounts';
import { log } from '../util/log';
import {
DEFAULT_BLOCK_NUMBER_CONFIGS,
DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES,
} from '../util/onchainQuoteProviderConfigs';
import { routeToString } from '../util/routes';

import { Result } from './multicall-provider';
Expand Down Expand Up @@ -92,6 +96,14 @@ export type RouteWithQuotes<TRoute extends V3Route | V2Route | MixedRoute> = [
AmountQuote[]
];

/**
* Final consolidated return type of all on-chain quotes.
*/
export type OnChainQuotes<TRoute extends V3Route | V2Route | MixedRoute> = {
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
};

type QuoteBatchSuccess = {
status: 'success';
inputs: [string, string][];
Expand Down Expand Up @@ -141,10 +153,7 @@ export interface IOnChainQuoteProvider {
amountIns: CurrencyAmount[],
routes: TRoute[],
providerConfig?: ProviderConfig
): Promise<{
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
}>;
): Promise<OnChainQuotes<TRoute>>;

/**
* For every route, gets ane exactOut quote for every amount provided.
Expand All @@ -160,10 +169,7 @@ export interface IOnChainQuoteProvider {
amountOuts: CurrencyAmount[],
routes: TRoute[],
providerConfig?: ProviderConfig
): Promise<{
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
}>;
): Promise<OnChainQuotes<TRoute>>;
}

/**
Expand Down Expand Up @@ -264,12 +270,16 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
* @param successRateFailureOverrides The parameters for retries when we fail to get quotes.
* @param blockNumberConfig Parameters for adjusting which block we get quotes from, and how to handle block header not found errors.
* @param [quoterAddressOverride] Overrides the address of the quoter contract to use.
* @param metricsPrefix metrics prefix to differentiate between different instances of the quote provider.
*/
constructor(
protected chainId: ChainId,
protected provider: BaseProvider,
// Only supports Uniswap Multicall as it needs the gas limitting functionality.
protected multicall2Provider: UniswapMulticallProvider,
// retryOptions, batchParams, and gasErrorFailureOverride are always override in alpha-router
// so below default values are always not going to be picked up in prod.
// So we will not extract out below default values into constants.
protected retryOptions: QuoteRetryOptions = {
retries: DEFAULT_BATCH_RETRIES,
minTimeout: 25,
Expand All @@ -284,15 +294,13 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
gasLimitOverride: 1_500_000,
multicallChunk: 100,
},
protected successRateFailureOverrides: FailureOverrides = {
gasLimitOverride: 1_300_000,
multicallChunk: 110,
},
protected blockNumberConfig: BlockNumberConfig = {
baseBlockOffset: 0,
rollback: { enabled: false },
},
protected quoterAddressOverride?: string
// 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 quoterAddressOverride?: string,
protected metricsPrefix?: string
) {}

private getQuoterAddress(useMixedRouteQuoter: boolean): string {
Expand All @@ -317,10 +325,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
amountIns: CurrencyAmount[],
routes: TRoute[],
providerConfig?: ProviderConfig
): Promise<{
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
}> {
): Promise<OnChainQuotes<TRoute>> {
return this.getQuotesManyData(
amountIns,
routes,
Expand All @@ -333,10 +338,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
amountOuts: CurrencyAmount[],
routes: TRoute[],
providerConfig?: ProviderConfig
): Promise<{
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
}> {
): Promise<OnChainQuotes<TRoute>> {
return this.getQuotesManyData(
amountOuts,
routes,
Expand All @@ -352,10 +354,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
routes: TRoute[],
functionName: 'quoteExactInput' | 'quoteExactOutput',
_providerConfig?: ProviderConfig
): Promise<{
routesWithQuotes: RouteWithQuotes<TRoute>[];
blockNumber: BigNumber;
}> {
): Promise<OnChainQuotes<TRoute>> {
const useMixedRouteQuoter =
routes.some((route) => route.protocol === Protocol.V2) ||
routes.some((route) => route.protocol === Protocol.MIXED);
Expand Down Expand Up @@ -420,9 +419,13 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} and block number: ${await providerConfig.blockNumber} [Original before offset: ${originalBlockNumber}].`
);

metric.putMetric('QuoteBatchSize', inputs.length, MetricLoggerUnit.Count);
metric.putMetric(
`QuoteBatchSize_${ID_TO_NETWORK_NAME(this.chainId)}`,
`${this.metricsPrefix}QuoteBatchSize`,
inputs.length,
MetricLoggerUnit.Count
);
metric.putMetric(
`${this.metricsPrefix}QuoteBatchSize_${ID_TO_NETWORK_NAME(this.chainId)}`,
inputs.length,
MetricLoggerUnit.Count
);
Expand Down Expand Up @@ -593,7 +596,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
if (error instanceof BlockConflictError) {
if (!haveRetriedForBlockConflictError) {
metric.putMetric(
'QuoteBlockConflictErrorRetry',
`${this.metricsPrefix}QuoteBlockConflictErrorRetry`,
1,
MetricLoggerUnit.Count
);
Expand All @@ -604,7 +607,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} else if (error instanceof ProviderBlockHeaderError) {
if (!haveRetriedForBlockHeader) {
metric.putMetric(
'QuoteBlockHeaderNotFoundRetry',
`${this.metricsPrefix}QuoteBlockHeaderNotFoundRetry`,
1,
MetricLoggerUnit.Count
);
Expand Down Expand Up @@ -644,7 +647,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} else if (error instanceof ProviderTimeoutError) {
if (!haveRetriedForTimeout) {
metric.putMetric(
'QuoteTimeoutRetry',
`${this.metricsPrefix}QuoteTimeoutRetry`,
1,
MetricLoggerUnit.Count
);
Expand All @@ -653,7 +656,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} else if (error instanceof ProviderGasError) {
if (!haveRetriedForOutOfGas) {
metric.putMetric(
'QuoteOutOfGasExceptionRetry',
`${this.metricsPrefix}QuoteOutOfGasExceptionRetry`,
1,
MetricLoggerUnit.Count
);
Expand All @@ -665,7 +668,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} else if (error instanceof SuccessRateError) {
if (!haveRetriedForSuccessRate) {
metric.putMetric(
'QuoteSuccessRateRetry',
`${this.metricsPrefix}QuoteSuccessRateRetry`,
1,
MetricLoggerUnit.Count
);
Expand All @@ -681,7 +684,7 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} else {
if (!haveRetriedForUnknownReason) {
metric.putMetric(
'QuoteUnknownReasonRetry',
`${this.metricsPrefix}QuoteUnknownReasonRetry`,
1,
MetricLoggerUnit.Count
);
Expand Down Expand Up @@ -770,31 +773,31 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
);

metric.putMetric(
'QuoteApproxGasUsedPerSuccessfulCall',
`${this.metricsPrefix}QuoteApproxGasUsedPerSuccessfulCall`,
approxGasUsedPerSuccessCall,
MetricLoggerUnit.Count
);

metric.putMetric(
'QuoteNumRetryLoops',
`${this.metricsPrefix}QuoteNumRetryLoops`,
finalAttemptNumber - 1,
MetricLoggerUnit.Count
);

metric.putMetric(
'QuoteTotalCallsToProvider',
`${this.metricsPrefix}QuoteTotalCallsToProvider`,
totalCallsMade,
MetricLoggerUnit.Count
);

metric.putMetric(
'QuoteExpectedCallsToProvider',
`${this.metricsPrefix}QuoteExpectedCallsToProvider`,
expectedCallsMade,
MetricLoggerUnit.Count
);

metric.putMetric(
'QuoteNumRetriedCalls',
`${this.metricsPrefix}QuoteNumRetriedCalls`,
totalCallsMade - expectedCallsMade,
MetricLoggerUnit.Count
);
Expand All @@ -812,7 +815,10 @@ export class OnChainQuoteProvider implements IOnChainQuoteProvider {
} attempt loops. Total calls made to provider: ${totalCallsMade}. Have retried for timeout: ${haveRetriedForTimeout}`
);

return { routesWithQuotes: routesQuotes, blockNumber };
return {
routesWithQuotes: routesQuotes,
blockNumber,
} as OnChainQuotes<TRoute>;
}

private partitionQuotes(
Expand Down
43 changes: 29 additions & 14 deletions src/routers/alpha-router/alpha-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ import {
buildTrade,
} from '../../util/methodParameters';
import { metric, MetricLoggerUnit } from '../../util/metric';
import {
BATCH_PARAMS,
BLOCK_NUMBER_CONFIGS,
DEFAULT_BATCH_PARAMS, DEFAULT_BLOCK_NUMBER_CONFIGS,
DEFAULT_GAS_ERROR_FAILURE_OVERRIDES,
DEFAULT_RETRY_OPTIONS,
DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES,
GAS_ERROR_FAILURE_OVERRIDES,
RETRY_OPTIONS,
SUCCESS_RATE_FAILURE_OVERRIDES
} from '../../util/onchainQuoteProviderConfigs';
import { UNSUPPORTED_TOKENS } from '../../util/unsupported-tokens';
import {
IRouter,
Expand Down Expand Up @@ -626,25 +637,29 @@ export class AlphaRouter
}
);
break;
case ChainId.POLYGON_MUMBAI:
case ChainId.SEPOLIA:
this.onChainQuoteProvider = new OnChainQuoteProvider(
chainId,
provider,
this.multicall2Provider,
RETRY_OPTIONS[chainId],
BATCH_PARAMS[chainId],
GAS_ERROR_FAILURE_OVERRIDES[chainId],
SUCCESS_RATE_FAILURE_OVERRIDES[chainId],
BLOCK_NUMBER_CONFIGS[chainId]
);
break;
default:
this.onChainQuoteProvider = new OnChainQuoteProvider(
chainId,
provider,
this.multicall2Provider,
{
retries: 2,
minTimeout: 100,
maxTimeout: 1000,
},
{
multicallChunk: 210,
gasLimitPerCall: 705_000,
quoteMinSuccessRate: 0.15,
},
{
gasLimitOverride: 2_000_000,
multicallChunk: 70,
}
DEFAULT_RETRY_OPTIONS,
DEFAULT_BATCH_PARAMS,
DEFAULT_GAS_ERROR_FAILURE_OVERRIDES,
DEFAULT_SUCCESS_RATE_FAILURE_OVERRIDES,
DEFAULT_BLOCK_NUMBER_CONFIGS,
);
break;
}
Expand Down
6 changes: 6 additions & 0 deletions src/util/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ export const QUOTER_V2_ADDRESSES: AddressMap = {
// TODO: Gnosis + Moonbeam contracts to be deployed
};

export const NEW_QUOTER_V2_ADDRESSES: AddressMap = {
...constructSameAddressMap('0x61fFE014bA17989E743c5F6cB21bF9697530B21e'),
[ChainId.POLYGON_MUMBAI]: '0x60e06b92bC94a665036C26feC5FF2A92E2d04c5f',
[ChainId.SEPOLIA]: '0x6650ab818c0a7efa72fc1404a878fef1fec8e058',
};

export const MIXED_ROUTE_QUOTER_V1_ADDRESSES: AddressMap = {
[ChainId.MAINNET]:
CHAIN_TO_ADDRESSES_MAP[ChainId.MAINNET].v1MixedRouteQuoterAddress,
Expand Down
Loading

0 comments on commit dfa0357

Please sign in to comment.