From a041d3bdf1719b1e11109ceafbf756b9678a0608 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Sat, 16 Dec 2023 15:12:03 -0500 Subject: [PATCH 1/2] feat: search for deposit id by chain We can now search an arbitrary deposit id on a given chain to find all of its information. This has been very helpful to resolve deposits when looking at fills. --- scripts/spokepool.ts | 68 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/scripts/spokepool.ts b/scripts/spokepool.ts index 29b340952..601086571 100644 --- a/scripts/spokepool.ts +++ b/scripts/spokepool.ts @@ -6,9 +6,20 @@ import { Contract, ethers, Signer } from "ethers"; import { LogDescription } from "@ethersproject/abi"; import { constants as sdkConsts, utils as sdkUtils } from "@across-protocol/sdk-v2"; import { ExpandedERC20__factory as ERC20 } from "@across-protocol/contracts-v2"; -import { BigNumber, formatFeePct, getNetworkName, getSigner, isDefined, resolveTokenSymbols, toBN } from "../src/utils"; +import { + BigNumber, + formatFeePct, + getDeploymentBlockNumber, + getNetworkName, + getSigner, + isDefined, + resolveTokenSymbols, + toBN, +} from "../src/utils"; import * as utils from "./utils"; +type Log = ethers.providers.Log; + type relayerFeeQuery = { originChainId: number; destinationChainId: number; @@ -215,23 +226,26 @@ async function dumpConfig(args: Record, _signer: Signer return true; } -// eslint-disable-next-line @typescript-eslint/no-unused-vars -async function fetchTxn(args: Record, _signer: Signer): Promise { - const { txnHash } = args; - const chainId = Number(args.chainId); - - if (!utils.validateChainIds([chainId])) { - usage(); // no return +async function _fetchDeposit(spokePool: Contract, _depositId: number | string): Promise { + const depositId = parseInt(_depositId.toString()); + if (isNaN(depositId)) { + throw new Error("No depositId specified"); } + const { chainId } = await spokePool.provider.getNetwork(); + const deploymentBlockNumber = getDeploymentBlockNumber("SpokePool", chainId); + const latestBlockNumber = await spokePool.provider.getBlockNumber(); + console.log(`Searching for depositId ${depositId} between ${deploymentBlockNumber} and ${latestBlockNumber}.`); + const filter = spokePool.filters.FundsDeposited(null, null, null, null, depositId); + return await spokePool.queryFilter(filter, deploymentBlockNumber, latestBlockNumber); +} + +async function _fetchTxn(spokePool: Contract, txnHash: string): Promise<{ deposits: Log[]; fills: Log[] }> { if (txnHash === undefined || typeof txnHash !== "string" || txnHash.length != 66 || !txnHash.startsWith("0x")) { throw new Error(`Missing or malformed transaction hash: ${txnHash}`); } - const provider = new ethers.providers.StaticJsonRpcProvider(utils.getProviderUrl(chainId)); - const spokePool = await utils.getSpokePoolContract(chainId); - - const txn = await provider.getTransactionReceipt(txnHash); + const txn = await spokePool.provider.getTransactionReceipt(txnHash); const fundsDeposited = spokePool.interface.getEventTopic("FundsDeposited"); const filledRelay = spokePool.interface.getEventTopic("FilledRelay"); const logs = txn.logs.filter(({ address }) => address === spokePool.address); @@ -244,6 +258,29 @@ async function fetchTxn(args: Record, _signer: Signer): } }); + return { deposits, fills }; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +async function fetchTxn(args: Record, _signer: Signer): Promise { + const { txnHash } = args; + const chainId = Number(args.chainId); + + if (!utils.validateChainIds([chainId])) { + usage(); // no return + } + + const provider = new ethers.providers.StaticJsonRpcProvider(utils.getProviderUrl(chainId)); + const spokePool = (await utils.getSpokePoolContract(chainId)).connect(provider); + + let deposits: Log[] = []; + let fills: Log[] = []; + if (args.depositId) { + deposits = await _fetchDeposit(spokePool, args.depositId); + } else if (txnHash) { + ({ deposits, fills } = await _fetchTxn(spokePool, txnHash as string)); + } + deposits.forEach((deposit) => { printDeposit(spokePool.interface.parseLog(deposit)); }); @@ -262,7 +299,7 @@ function usage(badInput?: string): boolean { "--from --to " + " --token --amount [--recipient ] [--decimals]"; const dumpConfigArgs = "--chainId"; - const fetchArgs = "--chainId --txnHash "; + const fetchArgs = "--chainId [--depositId | --txnHash ]"; const fillArgs = "--from --hash "; const pad = "deposit".length; @@ -283,10 +320,11 @@ function usage(badInput?: string): boolean { async function run(argv: string[]): Promise { const configOpts = ["chainId"]; const depositOpts = ["from", "to", "token", "amount", "recipient", "relayerFeePct", "message"]; - const fetchOpts = ["chainId", "transactionHash"]; + const fetchOpts = ["chainId", "transactionHash", "depositId"]; const fillOpts = []; + const fetchDepositOpts = ["chainId", "depositId"]; const opts = { - string: ["wallet", ...configOpts, ...depositOpts, ...fetchOpts, ...fillOpts], + string: ["wallet", ...configOpts, ...depositOpts, ...fetchOpts, ...fillOpts, ...fetchDepositOpts], boolean: ["decimals"], // @dev tbd whether this is good UX or not...may need to change. default: { wallet: "mnemonic", From e205d019bbb9092d8162cc2092af52cfd9869a5d Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 22 Dec 2023 03:48:31 +0100 Subject: [PATCH 2/2] Document findDeposit constraint --- scripts/spokepool.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/spokepool.ts b/scripts/spokepool.ts index 601086571..0bf4c7c1b 100644 --- a/scripts/spokepool.ts +++ b/scripts/spokepool.ts @@ -237,6 +237,10 @@ async function _fetchDeposit(spokePool: Contract, _depositId: number | string): const latestBlockNumber = await spokePool.provider.getBlockNumber(); console.log(`Searching for depositId ${depositId} between ${deploymentBlockNumber} and ${latestBlockNumber}.`); const filter = spokePool.filters.FundsDeposited(null, null, null, null, depositId); + + // @note: Querying over such a large block range typically only works on top-tier providers. + // @todo: Narrow the block range for the depositId, subject to this PR: + // https://github.com/across-protocol/sdk-v2/pull/476 return await spokePool.queryFilter(filter, deploymentBlockNumber, latestBlockNumber); }