8000 fix(sdk-router): gas.zip block height by ChiTimesChi · Pull Request #3675 · synapsecns/sanguine · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix(sdk-router): gas.zip block height #3675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/sdk-router/src/gaszip/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,29 @@ export const getChains = async (): Promise<Chains> => {
}
}

export const getGasZipBlockHeightMap = async (): Promise<
Map<number, number>
> => {
const response = await getWithTimeout(
'Gas.Zip API',
`${GAS_ZIP_API_URL}/admin/indexer`,
GAS_ZIP_API_TIMEOUT
)
if (!response) {
return new Map()
}
const data: { chain: any; head: any }[] = await response.json()
return new Map(
data
.filter((item) => {
const chainNum = Number(item.chain)
const headNum = Number(item.head)
return Number.isInteger(chainNum) && Number.isInteger(headNum)
})
.map((item) => [Number(item.chain), Number(item.head)])
)
}

export const getGasZipQuote = async (
originChainId: number,
destChainId: number,
Expand Down
81 changes: 80 additions & 1 deletion packages/sdk-router/src/gaszip/gasZipModuleSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,24 @@ import {
SynapseModuleSet,
} from '../module'
import { ChainProvider } from '../router'
import { Chains, getChains, getGasZipQuote } from './api'
import {
Chains,
getChains,
getGasZipBlockHeightMap,
getGasZipQuote,
} from './api'
import { GasZipModule } from './gasZipModule'
import { applySlippage, encodeZapData } from '../swap'
import {
ETH_NATIVE_TOKEN_ADDRESS,
isNativeToken,
isSameAddress,
logExecutionTime,
logger,
} from '../utils'

const MEDIAN_TIME_GAS_ZIP = 30
const GAS_ZIP_MAX_BLOCK_AGE_MS = 5 * 60 * 1000

export class GasZipModuleSet extends SynapseModuleSet {
public readonly moduleName = 'Gas.zip'
Expand Down Expand Up @@ -125,6 +132,10 @@ export class GasZipModuleSet extends SynapseModuleSet {
if (!allowMultipleTxs && !isSameAddress(bridgeToken.destToken, toToken)) {
return undefined
}
const syncedPromise = this.checkBlockHeights(
bridgeToken.originChainId,
bridgeToken.destChainId
)
const quote = await getGasZipQuote(
bridgeToken.originChainId,
bridgeToken.destChainId,
Expand Down Expand Up @@ -154,6 +165,11 @@ export class GasZipModuleSet extends SynapseModuleSet {
toRecipient
),
}
// Verify that both chains are up to date before returning the route
const synced = await syncedPromise
if (!synced) {
return undefined
}
return route
}

Expand All @@ -168,6 +184,7 @@ export class GasZipModuleSet extends SynapseModuleSet {
tokenOut: string,
amountIn: BigNumberish
): Promise<BridgeRoute[]> {
const syncedPromise = this.checkBlockHeights(originChainId, destChainId)
// Check that both chains are supported by gas.zip
const supportedChainIds = await this.getAllChainIds()
if (
Expand Down Expand Up @@ -204,6 +221,11 @@ export class GasZipModuleSet extends SynapseModuleSet {
},
bridgeModuleName: this.moduleName,
}
// Verify that both chains are up to date before returning the route
const synced = await syncedPromise
if (!synced) {
return []
}
return [route]
}

Expand Down Expand Up @@ -293,4 +315,61 @@ export class GasZipModuleSet extends SynapseModuleSet {
).data,
})
}

/**
* Checks if the latest block heights reported by gas.zip are within the maximum age.
* Both chains must be up to date to enable the bridge.
*/
private async checkBlockHeights(
originChainId: number,
destChainId: number
): Promise<boolean> {
const blockHeightMap = await getGasZipBlockHeightMap()
const [originSynced, destSynced] = await Promise.all([
this.checkBlockHeight(originChainId, blockHeightMap.get(originChainId)),
this.checkBlockHeight(destChainId, blockHeightMap.get(destChainId)),
])
return originSynced && destSynced
}
Comment on lines +319 to +333
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Cache block-height map to cut per-request latency

checkBlockHeights calls getGasZipBlockHeightMap() every time; see the suggestion in api.ts to cache the result for a short TTL and reuse it here.

🤖 Prompt for AI Agents (early access)
In packages/sdk-router/src/gaszip/gasZipModuleSet.ts around lines 319 to 333, the method checkBlockHeights calls getGasZipBlockHeightMap() on every invocation, causing unnecessary latency. To fix this, implement caching for the block height map with a short TTL, similar to the approach suggested in api.ts, and reuse the cached result within checkBlockHeights instead of fetching it each time.


/**
* Checks if the block height is within the maximum age for a chain.
*/
private async checkBlockHeight(
chainId: number,
blockHeight?: number
): Promise<boolean> {
if (!blockHeight) {
logger.info(`Gas.zip block height not found for chain ${chainId}`)
return false
}
const provider = this.providers[chainId]
if (!provider) {
logger.info(`Provider not found for chain ${chainId}`)
return false
}
let block
try {
block = await provider.getBlock(blockHeight)
} catch (error) {
logger.error(
`Block height ${blockHeight} for chain ${chainId} not found: ${error}`
)
return false
}
if (!block) {
logger.error(
`Null block for chain ${chainId} at block height ${blockHeight}`
)
return false
}
const blockAge = Date.now() - block.timestamp * 1000
const result = 0 <= blockAge && blockAge <= GAS_ZIP_MAX_BLOCK_AGE_MS
if (!result) {
logger.info(
`Block height ${blockHeight} for chain ${chainId} is too old: ${blockAge} ms (allowed: 0 .. ${GAS_ZIP_MAX_BLOCK_AGE_MS} ms)`
)
}
return result
}
}
Loading
0