From f62a4102e9b5ff56f5fad05220d24baa3ad7a315 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:52:05 +0200 Subject: [PATCH] improve(SpokePoolClient): Multicall latestBlock updates (#750) The SpokePoolClient is currently throwing semi-regular errors on update. This seems to be particularly occurring against Polygon. The underlying reason for this is that the RPC quroum system is performing an eth_call against multiple providers, tagged at the latest block number as resolved by only one of them. Some providers may not have resolved that block number yet, in which case the query fails. The instance of this can presumably be reduced by bundling the two calls where this occurs into a single SpokePool multicall. As a side-benefit, it will reduce RPC consumption. --- package.json | 2 +- src/clients/SpokePoolClient.ts | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 86c652c1..fa011e24 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@across-protocol/sdk", "author": "UMA Team", - "version": "3.2.6", + "version": "3.2.7", "license": "AGPL-3.0", "homepage": "https://docs.across.to/reference/sdk", "files": [ diff --git a/src/clients/SpokePoolClient.ts b/src/clients/SpokePoolClient.ts index dfe32a2e..b462ce76 100644 --- a/src/clients/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient.ts @@ -499,21 +499,29 @@ export class SpokePoolClient extends BaseAbstractClient { }; }); + const { spokePool } = this; this.log("debug", `Updating SpokePool client for chain ${this.chainId}`, { eventsToQuery, searchConfig, - spokePool: this.spokePool.address, + spokePool: spokePool.address, }); const timerStart = Date.now(); - const [numberOfDeposits, currentTime, oldestTime, ...events] = await Promise.all([ - this.spokePool.numberOfDeposits({ blockTag: searchConfig.toBlock }), - this.spokePool.getCurrentTime({ blockTag: searchConfig.toBlock }), + const multicallFunctions = ["getCurrentTime", "numberOfDeposits"]; + const [multicallOutput, oldestTime, ...events] = await Promise.all([ + spokePool.callStatic.multicall( + multicallFunctions.map((f) => spokePool.interface.encodeFunctionData(f)), + { blockTag: searchConfig.toBlock } + ), this.spokePool.getCurrentTime({ blockTag: Math.max(searchConfig.fromBlock, this.deploymentBlock) }), ...eventSearchConfigs.map((config) => paginatedEventQuery(this.spokePool, config.filter, config.searchConfig)), ]); this.log("debug", `Time to query new events from RPC for ${this.chainId}: ${Date.now() - timerStart} ms`); + const [currentTime, numberOfDeposits] = multicallFunctions.map( + (fn, idx) => spokePool.interface.decodeFunctionResult(fn, multicallOutput[idx])[0] + ); + if (!BigNumber.isBigNumber(currentTime) || currentTime.lt(this.currentTime)) { const errMsg = BigNumber.isBigNumber(currentTime) ? `currentTime: ${currentTime} < ${toBN(this.currentTime)}`