Commit f2dfc570 authored by Moody Salem's avatar Moody Salem Committed by GitHub

fix: retry calls that return header not found errors (#2004)

parent 318252b6
...@@ -17,32 +17,23 @@ const DEFAULT_GAS_REQUIRED = 1_000_000 ...@@ -17,32 +17,23 @@ const DEFAULT_GAS_REQUIRED = 1_000_000
* Fetches a chunk of calls, enforcing a minimum block number constraint * Fetches a chunk of calls, enforcing a minimum block number constraint
* @param multicall multicall contract to fetch against * @param multicall multicall contract to fetch against
* @param chunk chunk of calls to make * @param chunk chunk of calls to make
* @param minBlockNumber minimum block number of the result set * @param blockNumber block number passed as the block tag in the eth_call
*/ */
async function fetchChunk( async function fetchChunk(
multicall: UniswapInterfaceMulticall, multicall: UniswapInterfaceMulticall,
chunk: Call[], chunk: Call[],
minBlockNumber: number
): Promise<{
results: { success: boolean; returnData: string }[]
// note we are not using this returned block number because layer 2 multicalls do not consistently return the L2 block number
// instead we are relying on the blockTag parameter and assume the returned data is at least as new as that block number
blockNumber: number blockNumber: number
}> { ): Promise<{ success: boolean; returnData: string }[]> {
console.debug('Fetching chunk', chunk, minBlockNumber) console.debug('Fetching chunk', chunk, blockNumber)
let resultsBlockNumber: number
let results: { success: boolean; returnData: string }[]
try { try {
const { blockNumber, returnData } = await multicall.callStatic.multicall( const { returnData } = await multicall.callStatic.multicall(
chunk.map((obj) => ({ chunk.map((obj) => ({
target: obj.address, target: obj.address,
callData: obj.callData, callData: obj.callData,
gasLimit: obj.gasRequired ?? DEFAULT_GAS_REQUIRED, gasLimit: obj.gasRequired ?? DEFAULT_GAS_REQUIRED,
})), })),
{ blockTag: minBlockNumber } { blockTag: blockNumber }
) )
resultsBlockNumber = blockNumber.toNumber()
results = returnData
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
returnData.forEach(({ gasUsed, returnData, success }, i) => { returnData.forEach(({ gasUsed, returnData, success }, i) => {
...@@ -60,16 +51,15 @@ async function fetchChunk( ...@@ -60,16 +51,15 @@ async function fetchChunk(
} }
}) })
} }
return returnData
} catch (error) { } catch (error) {
console.debug('Failed to fetch chunk', error) if (error.code === -32000 || error.message?.indexOf('header not found') !== -1) {
throw error throw new RetryableError(`header not found for block number ${blockNumber}`)
} }
if (resultsBlockNumber < minBlockNumber) { console.error('Failed to fetch chunk', error)
const retryMessage = `Fetched results for old block number: ${resultsBlockNumber.toString()} vs. ${minBlockNumber}` throw error
console.debug(retryMessage)
throw new RetryableError(retryMessage)
} }
return { results, blockNumber: resultsBlockNumber }
} }
/** /**
...@@ -190,7 +180,7 @@ export default function Updater(): null { ...@@ -190,7 +180,7 @@ export default function Updater(): null {
maxWait: 2500, maxWait: 2500,
}) })
promise promise
.then(({ results: returnData }) => { .then((returnData) => {
// accumulates the length of all previous indices // accumulates the length of all previous indices
const firstCallKeyIndex = chunkedCalls.slice(0, index).reduce<number>((memo, curr) => memo + curr.length, 0) const firstCallKeyIndex = chunkedCalls.slice(0, index).reduce<number>((memo, curr) => memo + curr.length, 0)
const lastCallKeyIndex = firstCallKeyIndex + returnData.length const lastCallKeyIndex = firstCallKeyIndex + returnData.length
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment