From ebe24d45a627799fb970aa843d0b760fb4399f1c Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Wed, 19 Feb 2025 12:21:19 +0000 Subject: [PATCH 01/13] chore: Drop V3 support --- src/clients/SpokePoolClient.ts | 13 +- src/clients/mocks/MockSpokePoolClient.ts | 99 +++----- src/interfaces/SpokePool.ts | 5 +- src/utils/SpokeUtils.ts | 65 ++++-- test/SpokePoolClient.v3Events.ts | 283 +++++++---------------- 5 files changed, 175 insertions(+), 290 deletions(-) diff --git a/src/clients/SpokePoolClient.ts b/src/clients/SpokePoolClient.ts index 7f5482c9f..c395b10b0 100644 --- a/src/clients/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient.ts @@ -328,9 +328,10 @@ export class SpokePoolClient extends BaseAbstractClient { * @param relayData RelayData field for the SlowFill request. * @returns The corresponding SlowFillRequest event if found, otherwise undefined. */ - public getSlowFillRequest(relayData: RelayData): SlowFillRequestWithBlock | undefined { - const messageHash = getMessageHash(relayData.message); - const hash = getRelayEventKey({ ...relayData, messageHash, destinationChainId: this.chainId }); + public getSlowFillRequest( + relayData: Omit & { messageHash: string } + ): SlowFillRequestWithBlock | undefined { + const hash = getRelayEventKey({ ...relayData, destinationChainId: this.chainId }); return this.slowFillRequests[hash]; } @@ -726,10 +727,6 @@ export class SpokePoolClient extends BaseAbstractClient { destinationChainId: this.chainId, } as SlowFillRequestWithBlock; - if (eventName === "RequestedV3SlowFill") { - slowFillRequest.messageHash = getMessageHash(slowFillRequest.message); - } - const depositHash = getRelayEventKey({ ...slowFillRequest, destinationChainId: this.chainId }); // Sanity check that this event is not a duplicate. @@ -742,7 +739,7 @@ export class SpokePoolClient extends BaseAbstractClient { } }; - ["RequestedV3SlowFill", "RequestedSlowFill"].forEach((event) => { + ["RequestedSlowFill"].forEach((event) => { if (eventsToQuery.includes(event)) { queryRequestedSlowFillEvents(event); } diff --git a/src/clients/mocks/MockSpokePoolClient.ts b/src/clients/mocks/MockSpokePoolClient.ts index 1958d9173..b30c1746b 100644 --- a/src/clients/mocks/MockSpokePoolClient.ts +++ b/src/clients/mocks/MockSpokePoolClient.ts @@ -26,7 +26,6 @@ import { bnZero, bnMax, bnOne, - toAddress, toBytes32, } from "../../utils"; import { SpokePoolClient, SpokePoolUpdate } from "../SpokePoolClient"; @@ -108,7 +107,7 @@ export class MockSpokePoolClient extends SpokePoolClient { }); // Update latestDepositIdQueried. - const idx = eventsToQuery.indexOf("V3FundsDeposited"); + const idx = eventsToQuery.indexOf("FundsDeposited"); const latestDepositId = (events[idx] ?? []).reduce( (depositId, event) => bnMax(depositId, event.args["depositId"] ?? bnZero), this.latestDepositIdQueried @@ -134,10 +133,6 @@ export class MockSpokePoolClient extends SpokePoolClient { return this._deposit("FundsDeposited", deposit); } - depositV3(deposit: Omit & Partial): Log { - return this._deposit("V3FundsDeposited", deposit); - } - protected _deposit(event: string, deposit: Omit & Partial): Log { const { blockNumber, transactionIndex } = deposit; let { depositId, destinationChainId, inputAmount, outputAmount } = deposit; @@ -145,12 +140,11 @@ export class MockSpokePoolClient extends SpokePoolClient { this.numberOfDeposits = depositId.add(bnOne); destinationChainId ??= random(1, 42161, false); - const addressModifier = event === "FundsDeposited" ? toBytes32 : toAddress; - const depositor = addressModifier(deposit.depositor ?? randomAddress()); - const recipient = addressModifier(deposit.recipient ?? depositor); - const inputToken = addressModifier(deposit.inputToken ?? randomAddress()); - const outputToken = addressModifier(deposit.outputToken ?? inputToken); - const exclusiveRelayer = addressModifier(deposit.exclusiveRelayer ?? ZERO_ADDRESS); + const depositor = toBytes32(deposit.depositor ?? randomAddress()); + const recipient = toBytes32(deposit.recipient ?? depositor); + const inputToken = toBytes32(deposit.inputToken ?? randomAddress()); + const outputToken = toBytes32(deposit.outputToken ?? inputToken); + const exclusiveRelayer = toBytes32(deposit.exclusiveRelayer ?? ZERO_ADDRESS); inputAmount ??= toBNWei(random(1, 1000, false)); outputAmount ??= inputAmount.mul(toBN("0.95")); @@ -185,10 +179,6 @@ export class MockSpokePoolClient extends SpokePoolClient { }); } - fillV3Relay(fill: Omit & { message: string } & Partial): Log { - return this._fillRelay("FilledV3Relay", fill); - } - fillRelay(fill: Omit & { message: string } & Partial): Log { return this._fillRelay("FilledRelay", fill); } @@ -205,13 +195,12 @@ export class MockSpokePoolClient extends SpokePoolClient { outputAmount ??= inputAmount; fillDeadline ??= getCurrentTime() + 60; - const addressModifier = event === "FilledRelay" ? toBytes32 : toAddress; - const depositor = addressModifier(fill.depositor ?? randomAddress()); - const recipient = addressModifier(fill.recipient ?? depositor); - const inputToken = addressModifier(fill.inputToken ?? randomAddress()); - const outputToken = addressModifier(fill.outputToken ?? ZERO_ADDRESS); - const exclusiveRelayer = addressModifier(fill.exclusiveRelayer ?? ZERO_ADDRESS); - const relayer = addressModifier(fill.relayer ?? randomAddress()); + const depositor = toBytes32(fill.depositor ?? randomAddress()); + const recipient = toBytes32(fill.recipient ?? depositor); + const inputToken = toBytes32(fill.inputToken ?? randomAddress()); + const outputToken = toBytes32(fill.outputToken ?? ZERO_ADDRESS); + const exclusiveRelayer = toBytes32(fill.exclusiveRelayer ?? ZERO_ADDRESS); + const relayer = toBytes32(fill.relayer ?? randomAddress()); const topics = [originChainId, depositId, relayer]; // @todo verify const message = fill.message ?? EMPTY_MESSAGE; @@ -244,25 +233,14 @@ export class MockSpokePoolClient extends SpokePoolClient { }, }; - const args = - event === "FilledRelay" - ? { - ..._args, - messageHash: getMessageHash(message), - relayExecutionInfo: { - ...relayExecutionInfo, - updatedMessageHash: getMessageHash(updatedMessage), - }, - } - : { - // FilledV3Relay - ..._args, - message, - relayExecutionInfo: { - ...relayExecutionInfo, - updatedMessage, - }, - }; + const args = { + ..._args, + messageHash: getMessageHash(message), + relayExecutionInfo: { + ...relayExecutionInfo, + updatedMessageHash: getMessageHash(updatedMessage), + }, + }; return this.eventManager.generateEvent({ event, @@ -274,17 +252,12 @@ export class MockSpokePoolClient extends SpokePoolClient { }); } - speedUpV3Deposit(speedUp: SpeedUp): Log { - return this._speedUpDeposit("RequestedSpeedUpV3Deposit", speedUp); - } - speedUpDeposit(speedUp: SpeedUp): Log { return this._speedUpDeposit("RequestedSpeedUpDeposit", speedUp); } protected _speedUpDeposit(event: string, speedUp: SpeedUp): Log { - const addressModifier = event === "RequestedSpeedUpDeposit" ? toBytes32 : toAddress; - const depositor = addressModifier(speedUp.depositor); + const depositor = toBytes32(speedUp.depositor); const topics = [speedUp.depositId, depositor]; const args = { ...speedUp }; @@ -295,7 +268,7 @@ export class MockSpokePoolClient extends SpokePoolClient { args: { ...args, depositor, - updatedRecipient: addressModifier(speedUp.updatedRecipient), + updatedRecipient: toBytes32(speedUp.updatedRecipient), }, }); } @@ -313,24 +286,16 @@ export class MockSpokePoolClient extends SpokePoolClient { }); } - requestV3SlowFill(request: Omit & Partial): Log { - return this._requestSlowFill("RequestedV3SlowFill", request); - } - - requestSlowFill(request: Omit & Partial): Log { + requestSlowFill(request: SlowFillRequest & Partial): Log { return this._requestSlowFill("RequestedSlowFill", request); } - protected _requestSlowFill( - event: string, - request: Omit & Partial - ): Log { + protected _requestSlowFill(event: string, request: SlowFillRequest & Partial): Log { const { originChainId, depositId } = request; const topics = [originChainId, depositId]; const args = { ...request }; - const addressModifier = event === "RequestedSlowFill" ? toBytes32 : toAddress; - const depositor = addressModifier(args.depositor ?? randomAddress()); + const depositor = toBytes32(args.depositor ?? randomAddress()); return this.eventManager.generateEvent({ event, @@ -339,19 +304,19 @@ export class MockSpokePoolClient extends SpokePoolClient { args: { ...args, depositor, - recipient: addressModifier(args.recipient ?? depositor), - inputToken: addressModifier(args.inputToken ?? randomAddress()), - outputToken: addressModifier(args.outputToken ?? ZERO_ADDRESS), - exclusiveRelayer: addressModifier(args.exclusiveRelayer ?? ZERO_ADDRESS), + recipient: toBytes32(args.recipient ?? depositor), + inputToken: toBytes32(args.inputToken ?? randomAddress()), + outputToken: toBytes32(args.outputToken ?? ZERO_ADDRESS), + exclusiveRelayer: toBytes32(args.exclusiveRelayer ?? ZERO_ADDRESS), }, blockNumber: request.blockNumber, transactionIndex: request.transactionIndex, }); } - // This is a simple wrapper around fillV3Relay(). + // This is a simple wrapper around fillRelay(). // rootBundleId and proof are discarded here - we have no interest in verifying that. - executeV3SlowRelayLeaf(leaf: Omit): Log { + executeSlowRelayLeaf(leaf: Omit): Log { const fill = { ...leaf.relayData, destinationChainId: this.chainId, @@ -366,7 +331,7 @@ export class MockSpokePoolClient extends SpokePoolClient { }, }; - return this.fillV3Relay(fill); + return this.fillRelay(fill); } executeRelayerRefundLeaf(refund: RelayerRefundExecution & Partial): Log { diff --git a/src/interfaces/SpokePool.ts b/src/interfaces/SpokePool.ts index 23b2c3aa8..329350349 100644 --- a/src/interfaces/SpokePool.ts +++ b/src/interfaces/SpokePool.ts @@ -1,11 +1,8 @@ import { SortableEvent } from "./Common"; -import { FilledV3RelayEvent, V3FundsDepositedEvent } from "../typechain"; import { SpokePoolClient } from "../clients"; import { BigNumber } from "../utils"; import { RelayerRefundLeaf } from "./HubPool"; -export type { FilledV3RelayEvent, V3FundsDepositedEvent }; - export interface RelayData { originChainId: number; depositor: string; @@ -79,7 +76,7 @@ export interface SpeedUp { export interface SpeedUpWithBlock extends SpeedUp, SortableEvent {} -export interface SlowFillRequest extends RelayData { +export interface SlowFillRequest extends Omit { messageHash: string; destinationChainId: number; } diff --git a/src/utils/SpokeUtils.ts b/src/utils/SpokeUtils.ts index 453589ef2..a4119ac7f 100644 --- a/src/utils/SpokeUtils.ts +++ b/src/utils/SpokeUtils.ts @@ -14,6 +14,51 @@ import { toBytes32 } from "./AddressUtils"; type BlockTag = providers.BlockTag; +/** + * @param spokePool SpokePool Contract instance. + * @param deposit Deopsit instance. + * @param repaymentChainId Optional repaymentChainId (defaults to destinationChainId). + * @returns An Ethers UnsignedTransaction instance. + */ +export function populateRelay( + spokePool: Contract, + deposit: Omit, + relayer: string, + repaymentChainId = deposit.destinationChainId +): Promise { + const RelayData = { + depositor: toBytes32(deposit.depositor), + recipient: toBytes32(deposit.recipient), + exclusiveRelayer: toBytes32(deposit.exclusiveRelayer), + inputToken: toBytes32(deposit.inputToken), + outputToken: toBytes32(deposit.outputToken), + inputAmount: deposit.inputAmount, + outputAmount: deposit.outputAmount, + originChainId: deposit.originChainId, + depositId: deposit.depositId, + fillDeadline: deposit.fillDeadline, + exclusivityDeadline: deposit.exclusivityDeadline, + message: deposit.message, + }; + if (isDefined(deposit.speedUpSignature)) { + assert(isDefined(deposit.updatedRecipient) && !isZeroAddress(deposit.updatedRecipient)); + assert(isDefined(deposit.updatedOutputAmount)); + assert(isDefined(deposit.updatedMessage)); + return spokePool.populateTransaction.fillRelayWithUpdatedDeposit( + RelayData, + repaymentChainId, + toBytes32(relayer), + deposit.updatedOutputAmount, + toBytes32(deposit.updatedRecipient), + deposit.updatedMessage, + deposit.speedUpSignature, + { from: relayer } + ); + } + + return spokePool.populateTransaction.fillRelay(RelayData, repaymentChainId, toBytes32(relayer), { from: relayer }); +} + /** * @param spokePool SpokePool Contract instance. * @param deposit V3Deopsit instance. @@ -445,22 +490,14 @@ export async function findFillEvent( const maxBlockLookBack = 0; const [fromBlock, toBlock] = [blockNumber, blockNumber]; - const query = ( - await Promise.all([ - paginatedEventQuery( - spokePool, - spokePool.filters.FilledRelay(null, null, null, null, null, relayData.originChainId, relayData.depositId), - { fromBlock, toBlock, maxBlockLookBack } - ), - paginatedEventQuery( - spokePool, - spokePool.filters.FilledV3Relay(null, null, null, null, null, relayData.originChainId, relayData.depositId), - { fromBlock, toBlock, maxBlockLookBack } - ), - ]) - ).flat(); + const query = await paginatedEventQuery( + spokePool, + spokePool.filters.FilledRelay(null, null, null, null, null, relayData.originChainId, relayData.depositId), + { fromBlock, toBlock, maxBlockLookBack } + ); if (query.length === 0) throw new Error(`Failed to find fill event at block ${blockNumber}`); const event = query[0]; + // In production the chainId returned from the provider matches 1:1 with the actual chainId. Querying the provider // object saves an RPC query because the chainId is cached by StaticJsonRpcProvider instances. In hre, the SpokePool // may be configured with a different chainId than what is returned by the provider. diff --git a/test/SpokePoolClient.v3Events.ts b/test/SpokePoolClient.v3Events.ts index af482b4a3..7bba07c1c 100644 --- a/test/SpokePoolClient.v3Events.ts +++ b/test/SpokePoolClient.v3Events.ts @@ -2,7 +2,7 @@ import { expect } from "chai"; import { utils as sdkUtils } from "../src"; import { DEFAULT_CONFIG_STORE_VERSION, GLOBAL_CONFIG_STORE_KEYS } from "../src/clients"; import { MockConfigStoreClient, MockHubPoolClient, MockSpokePoolClient } from "../src/clients/mocks"; -import { ZERO_ADDRESS } from "../src/constants"; +import { ZERO_ADDRESS, ZERO_BYTES } from "../src/constants"; import { DepositWithBlock, FillWithBlock, @@ -12,7 +12,16 @@ import { SpeedUp, TokensBridged, } from "../src/interfaces"; -import { bnOne, getCurrentTime, getMessageHash, isDefined, randomAddress, toAddress, toBN } from "../src/utils"; +import { + bnOne, + getCurrentTime, + getMessageHash, + isDefined, + randomAddress, + toAddress, + toBytes32, + toBN, +} from "../src/utils"; import { SignerWithAddress, createSpyLogger, @@ -30,10 +39,10 @@ describe("SpokePoolClient: Event Filtering", function () { const random = () => Math.round(Math.random() * 1e6); const randomBytes = (n: number): string => ethers.utils.hexlify(ethers.utils.randomBytes(n)); - const fundsDepositedEvents = ["FundsDeposited", "V3FundsDeposited"]; - const slowFillRequestedEvents = ["RequestedSlowFill", "RequestedV3SlowFill"]; - const speedUpEvents = ["RequestedSpeedUpDeposit", "RequestedSpeedUpV3Deposit"]; - const filledRelayEvents = ["FilledRelay", "FilledV3Relay"]; + const fundsDepositedEvents = ["FundsDeposited"]; + const slowFillRequestedEvents = ["RequestedSlowFill"]; + const speedUpEvents = ["RequestedSpeedUpDeposit"]; + const filledRelayEvents = ["FilledRelay"]; let owner: SignerWithAddress; let chainIds: number[]; @@ -46,17 +55,6 @@ describe("SpokePoolClient: Event Filtering", function () { const logger = createSpyLogger().spyLogger; - const generateV3Deposit = ( - spokePoolClient: MockSpokePoolClient, - quoteTimestamp?: number, - inputToken?: string - ): Log => { - inputToken ??= randomAddress(); - const message = randomBytes(32); - quoteTimestamp ??= getCurrentTime() - 10; - return spokePoolClient.depositV3({ destinationChainId, inputToken, message, quoteTimestamp } as DepositWithBlock); - }; - const generateDeposit = (spokePoolClient: MockSpokePoolClient, quoteTimestamp?: number, inputToken?: string): Log => { inputToken ??= randomAddress(); const message = randomBytes(32); @@ -68,7 +66,7 @@ describe("SpokePoolClient: Event Filtering", function () { [owner] = await ethers.getSigners(); // Sanity Check: Ensure that owner.provider is defined - expect(owner.provider).to.not.be.undefined; + expect(owner.provider).to.exist; if (owner.provider === undefined) { throw new Error("owner.provider is undefined"); } @@ -130,12 +128,12 @@ describe("SpokePoolClient: Event Filtering", function () { destinationSpokePoolClient = spokePoolClients[destinationChainId]; }); - it("Correctly retrieves V3FundsDeposited events", async function () { + it("Correctly retrieves FundsDeposited events", async function () { // Inject a series of DepositWithBlock events. const depositEvents: Log[] = []; for (let idx = 0; idx < 10; ++idx) { - depositEvents.push(generateV3Deposit(originSpokePoolClient)); + depositEvents.push(generateDeposit(originSpokePoolClient)); } await originSpokePoolClient.update(fundsDepositedEvents); @@ -147,13 +145,13 @@ describe("SpokePoolClient: Event Filtering", function () { const expectedDeposit = depositEvents[idx]; expect(depositEvent.blockNumber).to.equal(expectedDeposit.blockNumber); - const expectedInputToken = expectedDeposit.args!.inputToken; - expect(depositEvent.inputToken).to.equal(expectedInputToken); + const expectedInputToken = expectedDeposit.args.inputToken; + expect(toBytes32(depositEvent.inputToken)).to.equal(expectedInputToken); }); }); it("Maps multiple fills for same deposit ID + origin chain ID to same deposit", async function () { - const depositEvent = generateV3Deposit(originSpokePoolClient); + const depositEvent = generateDeposit(originSpokePoolClient); await originSpokePoolClient.update(fundsDepositedEvents); let deposit = originSpokePoolClient.getDeposits().at(-1); expect(deposit).to.exist; @@ -161,10 +159,10 @@ describe("SpokePoolClient: Event Filtering", function () { expect(deposit.depositId).to.equal(depositEvent.args!.depositId); // Mock invalid fills: - destinationSpokePoolClient.fillV3Relay( + destinationSpokePoolClient.fillRelay( fillFromDeposit({ ...deposit, exclusivityDeadline: deposit.exclusivityDeadline + 2 }, randomAddress()) ); - destinationSpokePoolClient.fillV3Relay( + destinationSpokePoolClient.fillRelay( fillFromDeposit({ ...deposit, exclusivityDeadline: deposit.exclusivityDeadline + 1 }, randomAddress()) ); await destinationSpokePoolClient.update(filledRelayEvents); @@ -198,17 +196,17 @@ describe("SpokePoolClient: Event Filtering", function () { // Inject a DepositWithBlock event that should have the `fromLiteChain` flag set to false. // This is done by setting the quote timestamp to before the first lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp - 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp - 1); // Inject a DepositWithBlock event that should have the `fromLiteChain` flag set to true. // This is done by setting the quote timestamp to after the first lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp + 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp + 1); // Inject a DepositWithBlock event that should have the `fromLiteChain` flag set to false. // This is done by setting the quote timestamp to after the second lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate2.timestamp + 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate2.timestamp + 1); // Set the config store client on the originSpokePoolClient so that it can access the lite chain indices updates. originSpokePoolClient.setConfigStoreClient(configStoreClient); - await originSpokePoolClient.update(["V3FundsDeposited"]); + await originSpokePoolClient.update(fundsDepositedEvents); // Of the three deposits, the first and third should have the `fromLiteChain` flag set to false. const deposits = originSpokePoolClient.getDeposits(); @@ -243,17 +241,17 @@ describe("SpokePoolClient: Event Filtering", function () { // Inject a DepositWithBlock event that should have the `toLiteChain` flag set to false. // This is done by setting the quote timestamp to before the first lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp - 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp - 1); // Inject a DepositWithBlock event that should have the `toLiteChain` flag set to true. // This is done by setting the quote timestamp to after the first lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp + 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate1.timestamp + 1); // Inject a DepositWithBlock event that should have the `toLiteChain` flag set to false. // This is done by setting the quote timestamp to after the second lite chain update. - generateV3Deposit(originSpokePoolClient, liteChainIndicesUpdate2.timestamp + 1); + generateDeposit(originSpokePoolClient, liteChainIndicesUpdate2.timestamp + 1); // Set the config store client on the originSpokePoolClient so that it can access the lite chain indices updates. originSpokePoolClient.setConfigStoreClient(configStoreClient); - await originSpokePoolClient.update(["V3FundsDeposited"]); + await originSpokePoolClient.update(fundsDepositedEvents); // Of the three deposits, the first and third should have the `toLiteChain` flag set to false. const deposits = originSpokePoolClient.getDeposits(); @@ -274,13 +272,13 @@ describe("SpokePoolClient: Event Filtering", function () { hubPoolClient.setTokenMapping(hubPoolToken, destinationChainId, outputToken); hubPoolClient.setDefaultRealizedLpFeePct(toBNWei("0.0001")); - const _deposit = spokePoolClient.depositV3({ + const _deposit = spokePoolClient.deposit({ originChainId, destinationChainId, inputToken, outputToken: ZERO_ADDRESS, // outputToken must _not_ be ZERO_ADDRESS after SpokePoolClient ingestion. } as DepositWithBlock); - expect(_deposit?.args?.outputToken).to.equal(ZERO_ADDRESS); + expect(_deposit?.args?.outputToken).to.equal(toBytes32(ZERO_ADDRESS)); await spokePoolClient.update(fundsDepositedEvents); @@ -288,6 +286,7 @@ describe("SpokePoolClient: Event Filtering", function () { expect(deposit).to.exist; expect(deposit.inputToken).to.equal(inputToken); + expect(deposit.outputToken).to.not.equal(ZERO_ADDRESS); expect(deposit.outputToken).to.equal(outputToken); }); @@ -296,22 +295,22 @@ describe("SpokePoolClient: Event Filtering", function () { const requests: Log[] = []; const slowFillRequestFromDeposit = (deposit: DepositWithBlock): SlowFillRequest => { - const { blockNumber, ...partialDeposit } = deposit; - return { ...partialDeposit }; + const { blockNumber, message, ...partialDeposit } = deposit; + return { ...partialDeposit, messageHash: getMessageHash(message) }; }; for (let idx = 0; idx < 10; ++idx) { - const depositEvent = generateV3Deposit(originSpokePoolClient); + const depositEvent = generateDeposit(originSpokePoolClient); await originSpokePoolClient.update(fundsDepositedEvents); let deposit = originSpokePoolClient.getDeposits().at(-1); - expect(deposit).to.not.be.undefined; + expect(deposit).to.exist; deposit = deposit!; - expect(deposit.depositId).to.equal(depositEvent.args!.depositId); + expect(deposit.depositId).to.equal(depositEvent.args.depositId); const slowFillRequest = slowFillRequestFromDeposit(deposit); - requests.push(destinationSpokePoolClient.requestV3SlowFill(slowFillRequest as SlowFillRequestWithBlock)); + requests.push(destinationSpokePoolClient.requestSlowFill(slowFillRequest)); } await destinationSpokePoolClient.update(slowFillRequestedEvents); @@ -319,54 +318,53 @@ describe("SpokePoolClient: Event Filtering", function () { const slowFillRequests = destinationSpokePoolClient.getSlowFillRequests(); expect(slowFillRequests.length).to.equal(requests.length); - requests.forEach((event) => { - let { args } = event; - expect(args).to.not.be.undefined; - args = args!; - + requests.forEach(({ args }) => { const relayData = { depositId: args.depositId, originChainId: args.originChainId, - depositor: args.depositor, - recipient: args.recipient, - inputToken: args.inputToken, + depositor: toAddress(args.depositor), + recipient: toAddress(args.recipient), + inputToken: toAddress(args.inputToken), inputAmount: args.inputAmount, - outputToken: args.outputToken, + outputToken: toAddress(args.outputToken), outputAmount: args.outputAmount, - message: args.message, fillDeadline: args.fillDeadline, - exclusiveRelayer: args.exclusiveRelayer, + exclusiveRelayer: toAddress(args.exclusiveRelayer), exclusivityDeadline: args.exclusivityDeadline, }; - const slowFillRequest = destinationSpokePoolClient.getSlowFillRequest(relayData); - expect(slowFillRequest).to.not.be.undefined; + let slowFillRequest = destinationSpokePoolClient.getSlowFillRequest({ + ...relayData, + messageHash: args.messageHash, + }); + expect(slowFillRequest).to.exist; + slowFillRequest = slowFillRequest!; // The SpokePoolClient appends destinationChainId, so check for it specifically. - expect(slowFillRequest?.destinationChainId).to.not.be.undefined; - expect(slowFillRequest?.destinationChainId).to.equal(destinationChainId); + expect(slowFillRequest.destinationChainId).to.exist; + expect(slowFillRequest.destinationChainId).to.equal(destinationChainId); Object.entries(relayData).forEach( - ([k, v]) => expect(isDefined(v)).to.equal(true) && expect(slowFillRequest?.[k]).to.equal(v) + ([k, v]) => expect(isDefined(v)).to.equal(true) && expect(slowFillRequest[k]).to.equal(v) ); }); }); - it("Correctly retrieves FilledV3Relay events", async function () { - // Inject a series of v2DepositWithBlock and v3DepositWithBlock events. + it("Correctly retrieves FilledRelay events", async function () { + // Inject a series of DepositWithBlock events. const fillEvents: Log[] = []; const relayer = randomAddress(); for (let idx = 0; idx < 10; ++idx) { - const depositEvent = generateV3Deposit(originSpokePoolClient); + const depositEvent = generateDeposit(originSpokePoolClient); await originSpokePoolClient.update(fundsDepositedEvents); let deposit = originSpokePoolClient.getDeposits().at(-1); expect(deposit).to.exist; deposit = deposit!; - expect(deposit.depositId).to.equal(depositEvent.args!.depositId); + expect(deposit.depositId).to.equal(depositEvent.args.depositId); - const v3Fill = fillFromDeposit(deposit, relayer); - fillEvents.push(destinationSpokePoolClient.fillV3Relay(v3Fill as FillWithBlock & { message: string })); + const fill = fillFromDeposit(deposit, relayer); + fillEvents.push(destinationSpokePoolClient.fillRelay(fill as FillWithBlock & { message: string })); } await destinationSpokePoolClient.update(filledRelayEvents); @@ -381,7 +379,7 @@ describe("SpokePoolClient: Event Filtering", function () { // destinationChainId is appended by the SpokePoolClient for V3FundsDeposited events, so verify its correctness. expect(fillEvent.destinationChainId).to.equal(destinationChainId); - expect(fillEvent.outputToken).to.equal(expectedFill.args!.outputToken); + expect(toBytes32(fillEvent.outputToken)).to.equal(expectedFill.args.outputToken); }); }); @@ -403,14 +401,15 @@ describe("SpokePoolClient: Event Filtering", function () { const [depositor, recipient, inputToken, outputToken, exclusiveRelayer] = Array(5) .fill(0) .map((_) => ethers.utils.hexZeroPad(randomAddress(), 32)); - originSpokePoolClient.depositV3({ + + originSpokePoolClient.deposit({ depositor, recipient, inputToken, outputToken, exclusiveRelayer, } as DepositWithBlock); - await originSpokePoolClient.update(["V3FundsDeposited"]); + await originSpokePoolClient.update(fundsDepositedEvents); let deposit = originSpokePoolClient.getDeposits().at(-1); expect(deposit).to.exist; deposit = deposit!; @@ -427,8 +426,8 @@ describe("SpokePoolClient: Event Filtering", function () { const [depositor, updatedRecipient] = Array(2) .fill(0) .map((_) => ethers.utils.hexZeroPad(randomAddress(), 32)); - originSpokePoolClient.speedUpV3Deposit({ depositor, updatedRecipient, depositId: toBN(i) } as SpeedUp); - await originSpokePoolClient.update(["RequestedSpeedUpV3Deposit"]); + originSpokePoolClient.speedUpDeposit({ depositor, updatedRecipient, depositId: toBN(i) } as SpeedUp); + await originSpokePoolClient.update(speedUpEvents); let speedUp = originSpokePoolClient.getSpeedUps()[toAddress(depositor)][toBN(i).toString()].at(-1); expect(speedUp).to.exist; speedUp = speedUp!; @@ -442,7 +441,7 @@ describe("SpokePoolClient: Event Filtering", function () { const [depositor, recipient, inputToken, outputToken, exclusiveRelayer, relayer] = Array(6) .fill(0) .map((_) => ethers.utils.hexZeroPad(randomAddress(), 32)); - originSpokePoolClient.fillV3Relay({ + originSpokePoolClient.fillRelay({ depositor, recipient, inputToken, @@ -451,7 +450,8 @@ describe("SpokePoolClient: Event Filtering", function () { relayer, depositId: toBN(i), } as FillWithBlock & { message: string }); - await originSpokePoolClient.update(["FilledV3Relay"]); + await originSpokePoolClient.update(filledRelayEvents); + let relay = originSpokePoolClient.getFills().at(-1); expect(relay).to.exist; relay = relay!; @@ -469,7 +469,7 @@ describe("SpokePoolClient: Event Filtering", function () { const [depositor, recipient, inputToken, outputToken, exclusiveRelayer] = Array(5) .fill(0) .map((_) => ethers.utils.hexZeroPad(randomAddress(), 32)); - originSpokePoolClient.requestV3SlowFill({ + originSpokePoolClient.requestSlowFill({ depositor, recipient, inputToken, @@ -479,11 +479,12 @@ describe("SpokePoolClient: Event Filtering", function () { originChainId: 1, inputAmount: toBN(i), outputAmount: toBN(i), - message: "0x", + messageHash: ZERO_BYTES, fillDeadline: 0, exclusivityDeadline: 0, } as SlowFillRequestWithBlock); - await originSpokePoolClient.update(["RequestedV3SlowFill"]); + await originSpokePoolClient.update(slowFillRequestedEvents); + let slowFill = originSpokePoolClient.getSlowFillRequestsForOriginChain(1).at(-1); expect(slowFill).to.exist; slowFill = slowFill!; @@ -532,7 +533,7 @@ describe("SpokePoolClient: Event Filtering", function () { const relayExecutionInfo = { updatedRecipient, updatedOutputAmount: common.outputAmount, - updatedMessage: randomBytes(32), + updatedMessageHash: randomBytes(32), depositorSignature: randomBytes(32), }; @@ -575,8 +576,8 @@ describe("SpokePoolClient: Event Filtering", function () { logIndex: random(), }); - // RequestV3SlowFill - destinationSpokePoolClient.requestSlowFill({ ...common, message: randomBytes(32) }); + // RequestSlowFill + destinationSpokePoolClient.requestSlowFill({ ...common, messageHash: randomBytes(32) }); await originSpokePoolClient.update([ ...fundsDepositedEvents, @@ -639,128 +640,16 @@ describe("SpokePoolClient: Event Filtering", function () { } }); - describe("SpokePoolClient: Legacy messageHash Handling", function () { - it("Correctly appends messageHash", async function () { - for (const event of ["FundsDeposited", "V3FundsDeposited"]) { - const depositGenerator = event === "V3FundsDeposited" ? generateV3Deposit : generateDeposit; - const _deposit = depositGenerator(originSpokePoolClient); - expect(_deposit?.args?.messageHash).to.equal(undefined); - await originSpokePoolClient.update(fundsDepositedEvents); - - let deposit = originSpokePoolClient.getDeposit(_deposit.args.depositId); - expect(deposit).to.exist; - deposit = deposit!; - - // Both event types should include messageHash. - expect(deposit.messageHash).to.equal(getMessageHash(deposit.message)); - } - }); - - it("Correctly appends RequestedV3SlowFill messageHash", async function () { - for (const event of ["RequestedSlowFill", "RequestedV3SlowFill"]) { - const depositGenerator = event === "RequestedV3SlowFill" ? generateV3Deposit : generateDeposit; - const _deposit = depositGenerator(originSpokePoolClient); - expect(_deposit?.args?.messageHash).to.equal(undefined); - await originSpokePoolClient.update(fundsDepositedEvents); - - let deposit = originSpokePoolClient.getDeposit(_deposit.args.depositId); - expect(deposit).to.exist; - deposit = deposit!; - - if (event === "RequestedV3SlowFill") { - destinationSpokePoolClient.requestV3SlowFill({ ...deposit, blockNumber: undefined }); - } else { - destinationSpokePoolClient.requestSlowFill({ ...deposit, blockNumber: undefined }); - } - await destinationSpokePoolClient.update(slowFillRequestedEvents); - - let slowFillRequest = destinationSpokePoolClient.getSlowFillRequest(deposit); - expect(slowFillRequest).to.exist; - slowFillRequest = slowFillRequest!; - - expect(slowFillRequest.messageHash).to.equal(getMessageHash(deposit.message)); - } - }); - - it("Correctly appends RequestedSpeedUpDeposit messageHash", async function () { - for (const event of ["RequestedSpeedUpDeposit", "RequestedSpeedUpV3Deposit"]) { - const depositGenerator = event === "RequestedSpeedUpV3Deposit" ? generateV3Deposit : generateDeposit; - const _deposit = depositGenerator(originSpokePoolClient); - expect(_deposit?.args?.messageHash).to.equal(undefined); - await originSpokePoolClient.update(fundsDepositedEvents); - - let deposit = originSpokePoolClient.getDeposit(_deposit.args.depositId); - expect(deposit).to.exist; - deposit = deposit!; - - const speedUp = { - ...deposit, - updatedMessage: deposit.message, - updatedOutputAmount: deposit.outputAmount.sub(bnOne), - updatedRecipient: deposit.recipient, - depositorSignature: randomBytes(32), - }; - - if (event === "RequestedSpeedUpV3Deposit") { - originSpokePoolClient.speedUpV3Deposit(speedUp); - } else { - originSpokePoolClient.speedUpDeposit(speedUp); - } - await originSpokePoolClient.update(speedUpEvents); - - let updatedDeposit = originSpokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit); - expect(updatedDeposit).to.exist; - updatedDeposit = updatedDeposit!; - - expect(updatedDeposit.updatedMessage).to.equal(speedUp.updatedMessage); - expect(updatedDeposit.updatedRecipient).to.equal(speedUp.updatedRecipient); - expect(updatedDeposit.updatedOutputAmount).to.equal(speedUp.updatedOutputAmount); - expect(updatedDeposit.speedUpSignature).to.equal(speedUp.depositorSignature); - } - }); - - it("Correctly appends FilledV3Relay messageHash", async function () { - for (const event of ["FundsDeposited", "V3FundsDeposited"]) { - const depositGenerator = event === "V3FundsDeposited" ? generateV3Deposit : generateDeposit; - const _deposit = depositGenerator(originSpokePoolClient); - expect(_deposit?.args?.messageHash).to.equal(undefined); - await originSpokePoolClient.update(fundsDepositedEvents); - - let deposit = originSpokePoolClient.getDeposit(_deposit.args.depositId); - expect(deposit).to.exist; - deposit = deposit!; - - const relayer = randomAddress(); - - await destinationSpokePoolClient.update(); - let [fill] = destinationSpokePoolClient.getFillsForRelayer(relayer); - expect(fill).to.not.exist; - - if (event === "V3FundsDeposited") { - destinationSpokePoolClient.fillV3Relay(fillFromDeposit(deposit, relayer)); - } else { - destinationSpokePoolClient.fillRelay(fillFromDeposit(deposit, relayer)); - } - await destinationSpokePoolClient.update(filledRelayEvents); - - [fill] = destinationSpokePoolClient.getFillsForRelayer(relayer); - expect(fill).to.exist; - fill = fill!; - - expect(fill.messageHash).to.equal(getMessageHash(deposit.message)); - - const { relayExecutionInfo } = fill; - expect(relayExecutionInfo).to.exist; + it("Correctly appends FundsDeposited messageHash", async function () { + const _deposit = generateDeposit(originSpokePoolClient); + expect(_deposit?.args?.messageHash).to.equal(undefined); + await originSpokePoolClient.update(fundsDepositedEvents); - if (event === "V3FundsDeposited") { - expect(relayExecutionInfo.updatedMessage).to.exist; - } else { - expect(relayExecutionInfo.updatedMessage).to.not.exist; - } + let deposit = originSpokePoolClient.getDeposit(_deposit.args.depositId); + expect(deposit).to.exist; + deposit = deposit!; - expect(relayExecutionInfo.updatedMessageHash).to.exist; - expect(relayExecutionInfo.updatedMessageHash).to.equal(getMessageHash(deposit.message)); - } - }); + // Both event types should include messageHash. + expect(deposit.messageHash).to.equal(getMessageHash(deposit.message)); }); }); From 61bfa35c245cd15b0236a4e0f865e6803b14d652 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:20:17 +0000 Subject: [PATCH 02/13] Drop todo --- src/clients/mocks/MockSpokePoolClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clients/mocks/MockSpokePoolClient.ts b/src/clients/mocks/MockSpokePoolClient.ts index b30c1746b..4f55beed0 100644 --- a/src/clients/mocks/MockSpokePoolClient.ts +++ b/src/clients/mocks/MockSpokePoolClient.ts @@ -202,7 +202,7 @@ export class MockSpokePoolClient extends SpokePoolClient { const exclusiveRelayer = toBytes32(fill.exclusiveRelayer ?? ZERO_ADDRESS); const relayer = toBytes32(fill.relayer ?? randomAddress()); - const topics = [originChainId, depositId, relayer]; // @todo verify + const topics = [originChainId, depositId, relayer]; const message = fill.message ?? EMPTY_MESSAGE; const updatedMessage = fill.relayExecutionInfo?.updatedMessage ?? message; From 51117ef36ff59f993f21c0bbeaeaeae22129b8f2 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:34:30 +0000 Subject: [PATCH 03/13] Simplify --- src/clients/mocks/MockSpokePoolClient.ts | 12 ++++++++---- test/SpokePoolClient.v3Events.ts | 7 +++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/clients/mocks/MockSpokePoolClient.ts b/src/clients/mocks/MockSpokePoolClient.ts index 4f55beed0..3c0812c02 100644 --- a/src/clients/mocks/MockSpokePoolClient.ts +++ b/src/clients/mocks/MockSpokePoolClient.ts @@ -179,13 +179,13 @@ export class MockSpokePoolClient extends SpokePoolClient { }); } - fillRelay(fill: Omit & { message: string } & Partial): Log { + fillRelay(fill: Omit & { message?: string } & Partial): Log { return this._fillRelay("FilledRelay", fill); } protected _fillRelay( event: string, - fill: Omit & { message: string } & Partial + fill: Omit & { message?: string } & Partial ): Log { const { blockNumber, transactionIndex } = fill; let { originChainId, depositId, inputAmount, outputAmount, fillDeadline } = fill; @@ -286,11 +286,14 @@ export class MockSpokePoolClient extends SpokePoolClient { }); } - requestSlowFill(request: SlowFillRequest & Partial): Log { + requestSlowFill(request: Omit & Partial): Log { return this._requestSlowFill("RequestedSlowFill", request); } - protected _requestSlowFill(event: string, request: SlowFillRequest & Partial): Log { + protected _requestSlowFill( + event: string, + request: Omit & Partial + ): Log { const { originChainId, depositId } = request; const topics = [originChainId, depositId]; const args = { ...request }; @@ -303,6 +306,7 @@ export class MockSpokePoolClient extends SpokePoolClient { topics: topics.map((topic) => topic.toString()), args: { ...args, + destinationChainId: this.chainId, depositor, recipient: toBytes32(args.recipient ?? depositor), inputToken: toBytes32(args.inputToken ?? randomAddress()), diff --git a/test/SpokePoolClient.v3Events.ts b/test/SpokePoolClient.v3Events.ts index 7bba07c1c..b40dfe811 100644 --- a/test/SpokePoolClient.v3Events.ts +++ b/test/SpokePoolClient.v3Events.ts @@ -8,7 +8,6 @@ import { FillWithBlock, Log, SlowFillRequest, - SlowFillRequestWithBlock, SpeedUp, TokensBridged, } from "../src/interfaces"; @@ -364,7 +363,7 @@ describe("SpokePoolClient: Event Filtering", function () { expect(deposit.depositId).to.equal(depositEvent.args.depositId); const fill = fillFromDeposit(deposit, relayer); - fillEvents.push(destinationSpokePoolClient.fillRelay(fill as FillWithBlock & { message: string })); + fillEvents.push(destinationSpokePoolClient.fillRelay(fill)); } await destinationSpokePoolClient.update(filledRelayEvents); @@ -449,7 +448,7 @@ describe("SpokePoolClient: Event Filtering", function () { exclusiveRelayer, relayer, depositId: toBN(i), - } as FillWithBlock & { message: string }); + } as Omit); await originSpokePoolClient.update(filledRelayEvents); let relay = originSpokePoolClient.getFills().at(-1); @@ -482,7 +481,7 @@ describe("SpokePoolClient: Event Filtering", function () { messageHash: ZERO_BYTES, fillDeadline: 0, exclusivityDeadline: 0, - } as SlowFillRequestWithBlock); + }); await originSpokePoolClient.update(slowFillRequestedEvents); let slowFill = originSpokePoolClient.getSlowFillRequestsForOriginChain(1).at(-1); From 23482e5bb1a6809278d9baa58ef19a357cc5182e Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:42:06 +0000 Subject: [PATCH 04/13] lint --- test/SpokePoolClient.v3Events.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/SpokePoolClient.v3Events.ts b/test/SpokePoolClient.v3Events.ts index b40dfe811..13fbe13d1 100644 --- a/test/SpokePoolClient.v3Events.ts +++ b/test/SpokePoolClient.v3Events.ts @@ -3,14 +3,7 @@ import { utils as sdkUtils } from "../src"; import { DEFAULT_CONFIG_STORE_VERSION, GLOBAL_CONFIG_STORE_KEYS } from "../src/clients"; import { MockConfigStoreClient, MockHubPoolClient, MockSpokePoolClient } from "../src/clients/mocks"; import { ZERO_ADDRESS, ZERO_BYTES } from "../src/constants"; -import { - DepositWithBlock, - FillWithBlock, - Log, - SlowFillRequest, - SpeedUp, - TokensBridged, -} from "../src/interfaces"; +import { DepositWithBlock, FillWithBlock, Log, SlowFillRequest, SpeedUp, TokensBridged } from "../src/interfaces"; import { bnOne, getCurrentTime, From 56669016c9a1923961dcdd47240169a8795cc2f8 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 12:02:28 +0000 Subject: [PATCH 05/13] Additional cleanup --- src/clients/SpokePoolClient.ts | 39 +++++++++------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/clients/SpokePoolClient.ts b/src/clients/SpokePoolClient.ts index c395b10b0..c11a2e2b8 100644 --- a/src/clients/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient.ts @@ -122,13 +122,9 @@ export class SpokePoolClient extends BaseAbstractClient { "TokensBridged", "RelayedRootBundle", "ExecutedRelayerRefundRoot", - "V3FundsDeposited", "FundsDeposited", - "RequestedSpeedUpV3Deposit", "RequestedSpeedUpDeposit", - "RequestedV3SlowFill", "RequestedSlowFill", - "FilledV3Relay", "FilledRelay", ]; return Object.fromEntries( @@ -494,7 +490,7 @@ export class SpokePoolClient extends BaseAbstractClient { /** * @notice Return maximum of fill deadline buffer at start and end of block range. This is a contract * immutable state variable so we can't query other events to find its updates. - * @dev V3 deposits have a fill deadline which can be set to a maximum of fillDeadlineBuffer + deposit.block.timestamp. + * @dev Deposits have a fill deadline which can be set to a maximum of fillDeadlineBuffer + deposit.block.timestamp. * Therefore, we cannot evaluate a block range for expired deposits if the spoke pool client doesn't return us * deposits whose block.timestamp is within fillDeadlineBuffer of the end block time. As a conservative check, * we verify that the time between the end block timestamp and the first timestamp queried by the @@ -684,7 +680,7 @@ export class SpokePoolClient extends BaseAbstractClient { } }; - for (const event of ["V3FundsDeposited", "FundsDeposited"]) { + for (const event of ["FundsDeposited"]) { if (eventsToQuery.includes(event)) { await queryDepositEvents(event); } @@ -712,7 +708,7 @@ export class SpokePoolClient extends BaseAbstractClient { }; // Update deposits with speed up requests from depositor. - ["RequestedSpeedUpV3Deposit", "RequestedSpeedUpDeposit"].forEach((event) => { + ["RequestedSpeedUpDeposit"].forEach((event) => { if (eventsToQuery.includes(event)) { querySpeedUpDepositEvents(event); } @@ -763,11 +759,6 @@ export class SpokePoolClient extends BaseAbstractClient { destinationChainId: this.chainId, } as FillWithBlock; - if (eventName === "FilledV3Relay") { - fill.messageHash = getMessageHash(event.args.message); - fill.relayExecutionInfo.updatedMessageHash = getMessageHash(event.args.relayExecutionInfo.updatedMessage); - } - // Sanity check that this event is not a duplicate. const duplicateFill = this.fills[fill.originChainId]?.find((f) => duplicateEvent(fill, f)); if (duplicateFill) { @@ -781,7 +772,7 @@ export class SpokePoolClient extends BaseAbstractClient { }; // Update observed fills with ingested event data. - ["FilledV3Relay", "FilledRelay"].forEach((event) => { + ["FilledRelay"].forEach((event) => { if (eventsToQuery.includes(event)) { queryFilledRelayEvents(event); } @@ -944,23 +935,13 @@ export class SpokePoolClient extends BaseAbstractClient { ); const tStart = Date.now(); - // Check both V3FundsDeposited and FundsDeposited events to look for a specified depositId. const [fromBlock, toBlock] = [searchBounds.low, searchBounds.high]; const { maxBlockLookBack } = this.eventSearchConfig; - const query = ( - await Promise.all([ - paginatedEventQuery( - this.spokePool, - this.spokePool.filters.V3FundsDeposited(null, null, null, null, null, depositId), - { fromBlock, toBlock, maxBlockLookBack } - ), - paginatedEventQuery( - this.spokePool, - this.spokePool.filters.FundsDeposited(null, null, null, null, null, depositId), - { fromBlock, toBlock, maxBlockLookBack } - ), - ]) - ).flat(); + const query = await paginatedEventQuery( + this.spokePool, + this.spokePool.filters.FundsDeposited(null, null, null, null, null, depositId), + { fromBlock, toBlock, maxBlockLookBack } + ); const tStop = Date.now(); const event = query.find(({ args }) => args["depositId"].eq(depositId)); @@ -989,7 +970,7 @@ export class SpokePoolClient extends BaseAbstractClient { this.logger.debug({ at: "SpokePoolClient#findDeposit", - message: "Located V3 deposit outside of SpokePoolClient's search range", + message: "Located deposit outside of SpokePoolClient's search range", deposit, elapsedMs: tStop - tStart, }); From 97e4f4b65c3c7c14c783cdc48f8b5f7ffe540f94 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 13:00:13 +0000 Subject: [PATCH 06/13] Update tests 1/n --- test/SpokePoolClient.ValidateFill.ts | 140 ++++++++++++++------------- test/utils/utils.ts | 17 ++-- 2 files changed, 79 insertions(+), 78 deletions(-) diff --git a/test/SpokePoolClient.ValidateFill.ts b/test/SpokePoolClient.ValidateFill.ts index 0b78dc5d2..96403b3ae 100644 --- a/test/SpokePoolClient.ValidateFill.ts +++ b/test/SpokePoolClient.ValidateFill.ts @@ -11,6 +11,7 @@ import { queryHistoricalDepositForFill, DepositSearchResult, getBlockRangeForDepositId, + toAddress, } from "../src/utils"; import { ZERO_BYTES } from "../src/constants"; import { CHAIN_ID_TEST_LIST, originChainId, destinationChainId, repaymentChainId } from "./constants"; @@ -20,8 +21,8 @@ import { toBNWei, ethers, SignerWithAddress, - depositV3, - fillV3Relay, + deposit, + fillRelay, requestV3SlowFill, setupTokensForWallet, deploySpokePoolWithToken, @@ -121,7 +122,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Correctly matches fills with deposits", async function () { - const deposit_2 = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -130,10 +131,14 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const fill = await fillV3Relay(spokePool_2, deposit_2, relayer); + const fill = await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); - expect(validateFillForDeposit(fill, deposit_2)).to.deep.equal({ valid: true }); + // Events emit bytes32 but the SpokePoolClient truncates evm addresses back to bytes20. + ["depositor", "recipient", "inputToken", "outputToken", "exclusiveRelayer"].forEach( + (field) => (fill[field] = toAddress(fill[field])) + ); + expect(validateFillForDeposit(fill, depositEvent)).to.deep.equal({ valid: true }); const ignoredFields = [ "fromLiteChain", @@ -161,17 +166,17 @@ describe("SpokePoolClient: Fill Validation", function () { val = fill[field] + 1; } - const result = validateFillForDeposit(fill, { ...deposit_2, [field]: val }); + const result = validateFillForDeposit(fill, { ...depositEvent, [field]: val }); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith(`${field} mismatch`)).to.be.true; } // Verify that the underlying fill is untouched and still valid. - expect(validateFillForDeposit(fill, deposit_2)).to.deep.equal({ valid: true }); + expect(validateFillForDeposit(fill, depositEvent)).to.deep.equal({ valid: true }); }); it("Tracks v3 fill status", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -181,19 +186,19 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); - let filled = await relayFillStatus(spokePool_2, deposit); + let filled = await relayFillStatus(spokePool_2, depositEvent); expect(filled).to.equal(FillStatus.Unfilled); // Also test spoke client variant - filled = await spokePoolClient2.relayFillStatus(deposit); + filled = await spokePoolClient2.relayFillStatus(depositEvent); expect(filled).to.equal(FillStatus.Unfilled); - await fillV3Relay(spokePool_2, deposit, relayer); - filled = await relayFillStatus(spokePool_2, deposit); + await fillRelay(spokePool_2, depositEvent, relayer); + filled = await relayFillStatus(spokePool_2, depositEvent); expect(filled).to.equal(FillStatus.Filled); // Also test spoke client variant - filled = await spokePoolClient2.relayFillStatus(deposit); + filled = await spokePoolClient2.relayFillStatus(depositEvent); expect(filled).to.equal(FillStatus.Filled); }); @@ -201,7 +206,7 @@ describe("SpokePoolClient: Fill Validation", function () { const deposits: DepositWithBlock[] = []; for (let i = 0; i < 5; ++i) { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -210,7 +215,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - deposits.push(deposit); + deposits.push(depositEvent); } expect(deposits.length).to.be.greaterThan(0); @@ -219,7 +224,7 @@ describe("SpokePoolClient: Fill Validation", function () { fills.forEach((fillStatus) => expect(fillStatus).to.equal(FillStatus.Unfilled)); // Fill the first deposit and verify that the status updates correctly. - await fillV3Relay(spokePool_2, deposits[0], relayer); + await fillRelay(spokePool_2, deposits[0], relayer); fills = await fillStatusArray(spokePool_2, deposits); expect(fills.length).to.equal(deposits.length); expect(fills[0]).to.equal(FillStatus.Filled); @@ -235,14 +240,14 @@ describe("SpokePoolClient: Fill Validation", function () { fills.slice(2).forEach((fillStatus) => expect(fillStatus).to.equal(FillStatus.Unfilled)); // Fill all outstanding deposits and verify that the status updates correctly. - await Promise.all(deposits.slice(1).map((deposit) => fillV3Relay(spokePool_2, deposit, relayer))); + await Promise.all(deposits.slice(1).map((deposit) => fillRelay(spokePool_2, deposit, relayer))); fills = await fillStatusArray(spokePool_2, deposits); expect(fills.length).to.equal(deposits.length); fills.forEach((fillStatus) => expect(fillStatus).to.equal(FillStatus.Filled)); }); it("Accepts valid fills", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -251,21 +256,21 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - await fillV3Relay(spokePool_2, deposit, relayer); + await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); await spokePoolClient1.update(); - const [deposit_1] = spokePoolClient1.getDeposits(); + const [depositEvent_1] = spokePoolClient1.getDeposits(); const [fill_1] = spokePoolClient2.getFills(); // Some fields are expected to be dynamically populated by the client, but aren't in this environment. // Fill them in manually from the fill struct to get a valid comparison. - expect(validateFillForDeposit(fill_1, deposit_1)).to.deep.equal({ valid: true }); + expect(validateFillForDeposit(fill_1, depositEvent_1)).to.deep.equal({ valid: true }); }); it("Returns deposit matched with fill", async function () { - const _deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -275,17 +280,17 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); - const fill = await fillV3Relay(spokePool_2, _deposit, relayer); - expect(spokePoolClient2.getDepositForFill(fill)).to.equal(undefined); + const fill = await fillRelay(spokePool_2, depositEvent, relayer); + expect(spokePoolClient2.getDepositForFill(fill)).to.not.exist; await spokePoolClient1.update(); - const deposit = spokePoolClient1.getDepositForFill(fill); - expect(deposit).to.exist; - deposit = deposit!; + let _deposit = spokePoolClient1.getDepositForFill(fill); + expect(_deposit).to.exist; + _deposit = _deposit!; - expect(deposit) + expect(_deposit) .excludingEvery(["quoteBlockNumber", "fromLiteChain", "toLiteChain", "message"]) - .to.deep.equal(deposit); + .to.deep.equal(depositEvent); }); it("Get search bounds for deposit ID", async function () { @@ -296,10 +301,10 @@ describe("SpokePoolClient: Fill Validation", function () { spokePoolClient1.isUpdated = true; // Send 2 deposits and mine blocks between them to ensure deposits are in different blocks. - await depositV3(spokePool_1, destinationChainId, depositor, inputToken, inputAmount, outputToken, outputAmount); + await deposit(spokePool_1, destinationChainId, depositor, inputToken, inputAmount, outputToken, outputAmount); await mineRandomBlocks(); - const { blockNumber: deposit1Block } = await depositV3( + const { blockNumber: deposit1Block } = await deposit( spokePool_1, destinationChainId, depositor, @@ -310,9 +315,6 @@ describe("SpokePoolClient: Fill Validation", function () { ); await mineRandomBlocks(); - const [, deposit1Event] = await spokePool_1.queryFilter("FundsDeposited"); - const deposit1Block = deposit1Event.blockNumber; - // Throws when low < high await assertPromiseError( getBlockRangeForDepositId(bnZero, 1, 0, 10, spokePoolClient1), @@ -497,7 +499,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Can fetch older deposit matching fill", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -506,7 +508,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - await fillV3Relay(spokePool_2, deposit, relayer); + await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); @@ -523,12 +525,12 @@ describe("SpokePoolClient: Fill Validation", function () { const historicalDeposit = await queryHistoricalDepositForFill(spokePoolClient1, fill); assert.equal(historicalDeposit.found, true, "Test is broken"); // Help tsc to narrow the discriminated union. expect((historicalDeposit as Extract).deposit.depositId).to.deep.equal( - deposit.depositId + depositEvent.depositId ); }); it("Can fetch younger deposit matching fill", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -539,7 +541,7 @@ describe("SpokePoolClient: Fill Validation", function () { ); const { blockNumber: depositBlock } = deposit; - await fillV3Relay(spokePool_2, deposit, relayer); + await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); @@ -564,7 +566,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Loads fills from memory with deposit ID > spoke pool client's earliest deposit ID queried", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -573,7 +575,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const fill = await fillV3Relay(spokePool_2, deposit, relayer); + const fill = await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient1.update(); expect(spokePoolClient1.earliestDepositIdQueried == 0).is.true; @@ -589,7 +591,7 @@ describe("SpokePoolClient: Fill Validation", function () { it("Loads fills from memory with deposit ID < spoke pool client's latest deposit ID queried", async function () { // Send fill for deposit ID 0. - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -598,7 +600,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const fill = await fillV3Relay(spokePool_2, deposit, relayer); + const fill = await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient1.update(); // Manually override latest deposit ID queried so that its > deposit ID. spokePoolClient1.latestDepositIdQueried = 1; @@ -614,7 +616,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Ignores fills with deposit ID < first deposit ID in spoke pool", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -623,7 +625,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - await fillV3Relay(spokePool_2, deposit, relayer); + await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); @@ -639,7 +641,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Ignores fills with deposit ID > latest deposit ID in spoke pool", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -650,7 +652,7 @@ describe("SpokePoolClient: Fill Validation", function () { ); // Override the deposit ID that we are "filling" to be > 1, the latest deposit ID in spoke pool 1. - await fillV3Relay(spokePool_2, { ...deposit, depositId: deposit.depositId.add(1) }, relayer); + await fillRelay(spokePool_2, { ...depositEvent, depositId: depositEvent.depositId.add(1) }, relayer); await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); @@ -664,7 +666,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Ignores matching fills that mis-specify a deposit attribute", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -674,8 +676,8 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); - deposit.outputAmount = deposit.outputAmount.sub(bnOne); - const fill = await fillV3Relay(spokePool_2, deposit, relayer); + depositEvent.outputAmount = depositEvent.outputAmount.sub(bnOne); + const fill = await fillRelay(spokePool_2, depositEvent, relayer); await Promise.all([spokePoolClient1.update(), spokePoolClient2.update()]); @@ -685,7 +687,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Returns sped up deposit matched with fill", async function () { - const _deposit_1 = await depositV3( + const depositEvent_1 = await deposit( spokePool_1, destinationChainId, depositor, @@ -696,13 +698,13 @@ describe("SpokePoolClient: Fill Validation", function () { ); await spokePoolClient1.update(); - const fill_1 = await fillV3Relay(spokePool_2, _deposit_1, relayer); - const fill_2 = await fillV3Relay( + const fill_1 = await fillRelay(spokePool_2, depositEvent_1, relayer); + const fill_2 = await fillRelay( spokePool_2, { - ..._deposit_1, + ...depositEvent_1, recipient: relayer.address, - outputAmount: _deposit_1.outputAmount.div(2), + outputAmount: depositEvent_1.outputAmount.div(2), message: "0x12", }, relayer @@ -722,13 +724,13 @@ describe("SpokePoolClient: Fill Validation", function () { expect(fill_1.relayExecutionInfo.fillType === FillType.FastFill).to.be.true; expect(fill_2.relayExecutionInfo.fillType === FillType.FastFill).to.be.true; - const deposit = spokePoolClient1.getDepositForFill(fill_1); - expect(deposit).to.exist; - let result = validateFillForDeposit(fill_1, deposit); + const _deposit = spokePoolClient1.getDepositForFill(fill_1); + expect(_deposit).to.exist; + let result = validateFillForDeposit(fill_1, _deposit); expect(result.valid).to.be.true; - expect(spokePoolClient1.getDepositForFill(fill_2)).to.equal(undefined); + expect(spokePoolClient1.getDepositForFill(fill_2)).to.not.exist; - const _deposit_2 = await depositV3( + const depositEvent_2 = await deposit( spokePool_1, destinationChainId, depositor, @@ -737,43 +739,43 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const fill = await fillV3Relay(spokePool_2, _deposit_2, relayer); + const fill = await fillRelay(spokePool_2, depositEvent_2, relayer); await spokePoolClient2.update(); - expect(validateFillForDeposit(fill, _deposit_2)).to.deep.equal({ valid: true }); + expect(validateFillForDeposit(fill, depositEvent_2)).to.deep.equal({ valid: true }); // Changed the input token. - result = validateFillForDeposit(fill, { ..._deposit_2, inputToken: owner.address }); + result = validateFillForDeposit(fill, { ...depositEvent_2, inputToken: owner.address }); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("inputToken mismatch")).to.be.true; // Invalid input amount. - result = validateFillForDeposit({ ...fill, inputAmount: toBNWei(1337) }, _deposit_2); + result = validateFillForDeposit({ ...fill, inputAmount: toBNWei(1337) }, depositEvent_2); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("inputAmount mismatch")).to.be.true; // Changed the output token. - result = validateFillForDeposit(fill, { ..._deposit_2, outputToken: owner.address }); + result = validateFillForDeposit(fill, { ...depositEvent_2, outputToken: owner.address }); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("outputToken mismatch")).to.be.true; // Changed the output amount. - result = validateFillForDeposit({ ...fill, outputAmount: toBNWei(1337) }, _deposit_2); + result = validateFillForDeposit({ ...fill, outputAmount: toBNWei(1337) }, depositEvent_2); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("outputAmount mismatch")).to.be.true; // Invalid depositId. - result = validateFillForDeposit({ ...fill, depositId: toBN(1337) }, _deposit_2); + result = validateFillForDeposit({ ...fill, depositId: toBN(1337) }, depositEvent_2); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("depositId mismatch")).to.be.true; // Changed the depositor. - result = validateFillForDeposit({ ...fill, depositor: relayer.address }, _deposit_2); + result = validateFillForDeposit({ ...fill, depositor: relayer.address }, depositEvent_2); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("depositor mismatch")).to.be.true; // Changed the recipient. - result = validateFillForDeposit({ ...fill, recipient: relayer.address }, _deposit_2); + result = validateFillForDeposit({ ...fill, recipient: relayer.address }, depositEvent_2); expect(result.valid).to.be.false; expect((result as { reason: string }).reason.startsWith("recipient mismatch")).to.be.true; }); diff --git a/test/utils/utils.ts b/test/utils/utils.ts index ef634256f..4d0cbc348 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -344,7 +344,7 @@ async function _deposit( await spokePool .connect(signer) - .depositV3( + .deposit( addressModifier(depositor), addressModifier(recipient), addressModifier(inputToken), @@ -431,7 +431,6 @@ export async function requestV3SlowFill( inputAmount: args.inputAmount, outputToken: toAddress(args.outputToken), outputAmount: args.outputAmount, - message: args.message, messageHash: getMessageHash(args.message), fillDeadline: args.fillDeadline, exclusivityDeadline: args.exclusivityDeadline, @@ -443,7 +442,7 @@ export async function requestV3SlowFill( }; } -export async function fillV3Relay( +export async function fillRelay( spokePool: Contract, deposit: Omit, signer: SignerWithAddress, @@ -474,20 +473,20 @@ export async function fillV3Relay( depositId: toBN(args.depositId), originChainId: Number(args.originChainId), destinationChainId, - depositor: toAddress(args.depositor), - recipient: toAddress(args.recipient), - inputToken: toAddress(args.inputToken), + depositor: toBytes32(args.depositor), + recipient: toBytes32(args.recipient), + inputToken: toBytes32(args.inputToken), inputAmount: args.inputAmount, - outputToken: toAddress(args.outputToken), + outputToken: toBytes32(args.outputToken), outputAmount: args.outputAmount, messageHash: getMessageHash(args.message), fillDeadline: args.fillDeadline, exclusivityDeadline: args.exclusivityDeadline, - exclusiveRelayer: toAddress(args.exclusiveRelayer), + exclusiveRelayer: toBytes32(args.exclusiveRelayer), relayer: args.relayer, repaymentChainId: Number(args.repaymentChainId), relayExecutionInfo: { - updatedRecipient: toAddress(args.relayExecutionInfo.updatedRecipient), + updatedRecipient: toBytes32(args.relayExecutionInfo.updatedRecipient), updatedMessageHash: args.relayExecutionInfo.updatedMessageHash, updatedOutputAmount: args.relayExecutionInfo.updatedOutputAmount, fillType: args.relayExecutionInfo.fillType, From ea8c429edab1232ff44c8cb912be23161c9334a1 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 13:58:21 +0000 Subject: [PATCH 07/13] Update tests 2/n --- test/SpokePoolClient.SpeedUp.ts | 47 ++++++++++++----------- test/SpokePoolClient.ValidateFill.ts | 56 ++++++++++++++++------------ test/SpokePoolClient.fills.ts | 24 ++++++------ 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/test/SpokePoolClient.SpeedUp.ts b/test/SpokePoolClient.SpeedUp.ts index 5a059922d..fcb138e1e 100644 --- a/test/SpokePoolClient.SpeedUp.ts +++ b/test/SpokePoolClient.SpeedUp.ts @@ -10,7 +10,7 @@ import { createSpyLogger, deepEqualsWithBigNumber, deploySpokePoolWithToken, - depositV3, + deposit, enableRoutes, ethers, expect, @@ -55,7 +55,7 @@ describe("SpokePoolClient: SpeedUp", function () { }); it("Fetches speedup data associated with a deposit", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool, destinationChainId, depositor, @@ -67,14 +67,14 @@ describe("SpokePoolClient: SpeedUp", function () { await spokePoolClient.update(); // Should return the normal deposit object before any update is applied. - expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit)).to.deep.equal(deposit); + expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(depositEvent)).to.deep.equal(depositEvent); - const updatedOutputAmount = deposit.outputAmount.sub(bnOne); - const updatedRecipient = deposit.recipient; - const updatedMessage = deposit.message; + const updatedOutputAmount = depositEvent.outputAmount.sub(bnOne); + const updatedRecipient = depositEvent.recipient; + const updatedMessage = depositEvent.message; const signature = await getUpdatedV3DepositSignature( depositor, - deposit.depositId, + depositEvent.depositId, originChainId, updatedOutputAmount, toBytes32(updatedRecipient), @@ -85,7 +85,7 @@ describe("SpokePoolClient: SpeedUp", function () { .connect(depositor) .speedUpDeposit( toBytes32(depositor.address), - deposit.depositId, + depositEvent.depositId, updatedOutputAmount, toBytes32(updatedRecipient), updatedMessage, @@ -96,14 +96,14 @@ describe("SpokePoolClient: SpeedUp", function () { // After speedup should return the appended object with the new fee information and signature. const expectedDepositData: Deposit = { - ...deposit, - messageHash: getMessageHash(deposit.message), + ...depositEvent, + messageHash: getMessageHash(depositEvent.message), speedUpSignature: signature, updatedOutputAmount, updatedMessage, updatedRecipient, }; - const updatedDeposit = spokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit); + const updatedDeposit = spokePoolClient.appendMaxSpeedUpSignatureToDeposit(depositEvent); expect(deepEqualsWithBigNumber(updatedDeposit, expectedDepositData)).to.be.true; // Fetching deposits for the depositor should contain the correct fees. @@ -118,7 +118,7 @@ describe("SpokePoolClient: SpeedUp", function () { }); it("Selects the lowest outputAmount when multiple are presented", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool, destinationChainId, depositor, @@ -130,10 +130,10 @@ describe("SpokePoolClient: SpeedUp", function () { await spokePoolClient.update(); // Should return the normal deposit object before any update is applied. - expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit)).to.deep.equal(deposit); + expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(depositEvent)).to.deep.equal(depositEvent); const depositUpdates: SpeedUp[] = []; - const { depositId, recipient: updatedRecipient, message: updatedMessage } = deposit; + const { depositId, recipient: updatedRecipient, message: updatedMessage } = depositEvent; for (const updatedOutputAmount of [outputAmount.add(1), outputAmount, outputAmount.sub(1), outputAmount.sub(2)]) { const depositorSignature = await getUpdatedV3DepositSignature( depositor, @@ -173,13 +173,13 @@ describe("SpokePoolClient: SpeedUp", function () { : outputAmount; await spokePoolClient.update(); - let updatedDeposit = spokePoolClient.getDepositsForDestinationChain(deposit.destinationChainId).at(-1); + let updatedDeposit = spokePoolClient.getDepositsForDestinationChain(depositEvent.destinationChainId).at(-1); // Convoluted checks to help tsc narrow types. expect(updatedDeposit).to.exist; updatedDeposit = updatedDeposit!; - if (lowestOutputAmount.eq(deposit.outputAmount)) { + if (lowestOutputAmount.eq(depositEvent.outputAmount)) { expect(updatedDeposit.updatedOutputAmount).to.be.undefined; expect(updatedDeposit.speedUpSignature).to.be.undefined; expect(updatedDeposit.updatedRecipient).to.be.undefined; @@ -194,7 +194,7 @@ describe("SpokePoolClient: SpeedUp", function () { }); it("Ignores invalid updates", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool, destinationChainId, depositor, @@ -206,10 +206,10 @@ describe("SpokePoolClient: SpeedUp", function () { await spokePoolClient.update(); // Should return the normal deposit object before any update is applied. - expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit)).to.deep.equal(deposit); + expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(depositEvent)).to.deep.equal(depositEvent); - const { depositId, originChainId, recipient: updatedRecipient, message: updatedMessage } = deposit; - const updatedOutputAmount = deposit.outputAmount.sub(bnOne); + const { depositId, originChainId, recipient: updatedRecipient, message: updatedMessage } = depositEvent; + const updatedOutputAmount = depositEvent.outputAmount.sub(bnOne); // Independently toggle originChainId, depositId and depositor. Verify that a mismatch on these fields is not // attributed to the existing deposit. @@ -230,7 +230,7 @@ describe("SpokePoolClient: SpeedUp", function () { const speedUp = spokePool .connect(depositor) - .speedUpV3Deposit( + .speedUpDeposit( testDepositor.address, testDepositId, updatedOutputAmount, @@ -244,9 +244,8 @@ describe("SpokePoolClient: SpeedUp", function () { await assertPromiseError(speedUp); } - // The updated deposit information should never be attached to the - // deposit. - expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(deposit)).to.deep.equal(deposit); + // The updated deposit information should never be attached to the deposit. + expect(spokePoolClient.appendMaxSpeedUpSignatureToDeposit(depositEvent)).to.deep.equal(depositEvent); } }); }); diff --git a/test/SpokePoolClient.ValidateFill.ts b/test/SpokePoolClient.ValidateFill.ts index 96403b3ae..4c63add08 100644 --- a/test/SpokePoolClient.ValidateFill.ts +++ b/test/SpokePoolClient.ValidateFill.ts @@ -1,4 +1,4 @@ -import { DepositWithBlock, FillStatus, FillType } from "../src/interfaces"; +import { DepositWithBlock, FillStatus, FillType, RelayData } from "../src/interfaces"; import { SpokePoolClient } from "../src/clients"; import { bnOne, @@ -12,6 +12,7 @@ import { DepositSearchResult, getBlockRangeForDepositId, toAddress, + toBytes32, } from "../src/utils"; import { ZERO_BYTES } from "../src/constants"; import { CHAIN_ID_TEST_LIST, originChainId, destinationChainId, repaymentChainId } from "./constants"; @@ -53,6 +54,13 @@ let spokePoolClient2: SpokePoolClient, hubPoolClient: MockHubPoolClient; let spokePoolClient1: SpokePoolClient, configStoreClient: MockConfigStoreClient; describe("SpokePoolClient: Fill Validation", function () { + const truncateAddresses = (relayData: Omit): void => { + // Events emit bytes32 but the SpokePoolClient truncates evm addresses back to bytes20. + ["depositor", "recipient", "inputToken", "outputToken", "exclusiveRelayer"].forEach((field) => + relayData[field] = toAddress(relayData[field]) + ); + } + let inputToken: string, outputToken: string; let inputAmount: BigNumber, outputAmount: BigNumber; @@ -134,10 +142,7 @@ describe("SpokePoolClient: Fill Validation", function () { const fill = await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); - // Events emit bytes32 but the SpokePoolClient truncates evm addresses back to bytes20. - ["depositor", "recipient", "inputToken", "outputToken", "exclusiveRelayer"].forEach( - (field) => (fill[field] = toAddress(fill[field])) - ); + truncateAddresses(fill); expect(validateFillForDeposit(fill, depositEvent)).to.deep.equal({ valid: true }); const ignoredFields = [ @@ -281,6 +286,8 @@ describe("SpokePoolClient: Fill Validation", function () { ); const fill = await fillRelay(spokePool_2, depositEvent, relayer); + truncateAddresses(fill); + expect(spokePoolClient2.getDepositForFill(fill)).to.not.exist; await spokePoolClient1.update(); @@ -514,8 +521,8 @@ describe("SpokePoolClient: Fill Validation", function () { await assertPromiseError(queryHistoricalDepositForFill(spokePoolClient1, fill), "SpokePoolClient must be updated"); - // Set event search config from block to latest block so client doesn't see event. - spokePoolClient1.eventSearchConfig.fromBlock = await spokePool_1.provider.getBlockNumber(); + // Set event search config from block ahead of the deposit block so client doesn't see event. + spokePoolClient1.eventSearchConfig.fromBlock = depositEvent.blockNumber + 1; spokePoolClient1.firstBlockToSearch = spokePoolClient1.eventSearchConfig.fromBlock; await spokePoolClient1.update(); @@ -539,7 +546,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const { blockNumber: depositBlock } = deposit; + const { blockNumber: depositBlock } = depositEvent; await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); @@ -561,7 +568,7 @@ describe("SpokePoolClient: Fill Validation", function () { const historicalDeposit = await queryHistoricalDepositForFill(spokePoolClient1, fill); assert.equal(historicalDeposit.found, true, "Test is broken"); // Help tsc to narrow the discriminated union. expect((historicalDeposit as Extract).deposit.depositId).to.deep.equal( - deposit.depositId + depositEvent.depositId ); }); @@ -576,17 +583,19 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); const fill = await fillRelay(spokePool_2, depositEvent, relayer); + truncateAddresses(fill); + await spokePoolClient1.update(); - expect(spokePoolClient1.earliestDepositIdQueried == 0).is.true; + expect(spokePoolClient1.earliestDepositIdQueried.eq(bnZero)).is.true; // Client should NOT send RPC requests to fetch this deposit, instead it should load from memory. expect((await queryHistoricalDepositForFill(spokePoolClient1, fill)).found).is.true; expect(lastSpyLogIncludes(spy, "updated!")).is.true; // Now override earliest deposit ID queried so that its > deposit ID and check that client sends RPC requests. - spokePoolClient1.earliestDepositIdQueried = 1; + spokePoolClient1.earliestDepositIdQueried = bnOne; expect((await queryHistoricalDepositForFill(spokePoolClient1, fill)).found).is.true; - expect(lastSpyLogIncludes(spy, "Located V3 deposit outside of SpokePoolClient's search range")).is.true; + expect(lastSpyLogIncludes(spy, "Located deposit outside of SpokePoolClient's search range")).is.true; }); it("Loads fills from memory with deposit ID < spoke pool client's latest deposit ID queried", async function () { @@ -601,18 +610,20 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); const fill = await fillRelay(spokePool_2, depositEvent, relayer); + truncateAddresses(fill); + await spokePoolClient1.update(); // Manually override latest deposit ID queried so that its > deposit ID. - spokePoolClient1.latestDepositIdQueried = 1; + spokePoolClient1.latestDepositIdQueried = bnOne; // Client should NOT send RPC requests to fetch this deposit, instead it should load from memory. expect((await queryHistoricalDepositForFill(spokePoolClient1, fill)).found).is.true; expect(lastSpyLogIncludes(spy, "updated!")).is.true; // Now override latest deposit ID queried so that its < deposit ID and check that client sends RPC requests. - spokePoolClient1.latestDepositIdQueried = -1; + spokePoolClient1.latestDepositIdQueried = toBN("-1"); expect((await queryHistoricalDepositForFill(spokePoolClient1, fill)).found).is.true; - expect(lastSpyLogIncludes(spy, "Located V3 deposit outside of SpokePoolClient's search range")).is.true; + expect(lastSpyLogIncludes(spy, "Located deposit outside of SpokePoolClient's search range")).is.true; }); it("Ignores fills with deposit ID < first deposit ID in spoke pool", async function () { @@ -631,7 +642,7 @@ describe("SpokePoolClient: Fill Validation", function () { // Override the first spoke pool deposit ID that the client thinks is available in the contract. await spokePoolClient1.update(); - spokePoolClient1.firstDepositIdForSpokePool = deposit.depositId.add(1); + spokePoolClient1.firstDepositIdForSpokePool = depositEvent.depositId.add(1); expect(fill.depositId < spokePoolClient1.firstDepositIdForSpokePool).is.true; const search = await queryHistoricalDepositForFill(spokePoolClient1, fill); @@ -710,20 +721,15 @@ describe("SpokePoolClient: Fill Validation", function () { relayer ); - // Sanity Check: Ensure that fill2 is defined - expect(fill_2).to.not.be.undefined; - if (!fill_2) { - throw new Error("fill_2 is undefined"); - } - - expect(fill_1.relayExecutionInfo.updatedRecipient === depositor.address).to.be.true; - expect(fill_2.relayExecutionInfo.updatedRecipient === relayer.address).to.be.true; + expect(fill_1.relayExecutionInfo.updatedRecipient).to.eq(toBytes32(depositor.address)); + expect(fill_2.relayExecutionInfo.updatedRecipient).to.eq(toBytes32(relayer.address)); expect(fill_2.relayExecutionInfo.updatedMessageHash === ethers.utils.keccak256("0x12")).to.be.true; expect(fill_1.relayExecutionInfo.updatedMessageHash === ZERO_BYTES).to.be.true; expect(fill_1.relayExecutionInfo.updatedOutputAmount.eq(fill_2.relayExecutionInfo.updatedOutputAmount)).to.be.false; expect(fill_1.relayExecutionInfo.fillType === FillType.FastFill).to.be.true; expect(fill_2.relayExecutionInfo.fillType === FillType.FastFill).to.be.true; + [fill_1, fill_2].forEach(truncateAddresses); const _deposit = spokePoolClient1.getDepositForFill(fill_1); expect(_deposit).to.exist; let result = validateFillForDeposit(fill_1, _deposit); @@ -740,6 +746,8 @@ describe("SpokePoolClient: Fill Validation", function () { outputAmount ); const fill = await fillRelay(spokePool_2, depositEvent_2, relayer); + truncateAddresses(fill); + await spokePoolClient2.update(); expect(validateFillForDeposit(fill, depositEvent_2)).to.deep.equal({ valid: true }); diff --git a/test/SpokePoolClient.fills.ts b/test/SpokePoolClient.fills.ts index 6a57f85b0..5a2fbadf2 100644 --- a/test/SpokePoolClient.fills.ts +++ b/test/SpokePoolClient.fills.ts @@ -8,7 +8,7 @@ import { assertPromiseError, Contract, SignerWithAddress, - fillV3Relay, + fillRelay, createSpyLogger, deploySpokePoolWithToken, ethers, @@ -71,18 +71,18 @@ describe("SpokePoolClient: Fills", function () { }); it("Correctly fetches fill data single fill, single chain", async function () { - await fillV3Relay(spokePool, deposit, relayer1); - await fillV3Relay(spokePool, { ...deposit, depositId: deposit.depositId.add(1) }, relayer1); + await fillRelay(spokePool, deposit, relayer1); + await fillRelay(spokePool, { ...deposit, depositId: deposit.depositId.add(1) }, relayer1); await spokePoolClient.update(); expect(spokePoolClient.getFills().length).to.equal(2); }); it("Correctly fetches deposit data multiple fills, multiple chains", async function () { // Mix and match various fields to produce unique fills and verify they are all recorded by the SpokePoolClient. - await fillV3Relay(spokePool, deposit, relayer1); - await fillV3Relay(spokePool, { ...deposit, originChainId: originChainId2 }, relayer1); - await fillV3Relay(spokePool, { ...deposit, inputAmount: deposit.inputAmount.add(bnOne) }, relayer1); - await fillV3Relay(spokePool, { ...deposit, inputAmount: deposit.outputAmount.sub(bnOne) }, relayer2); + await fillRelay(spokePool, deposit, relayer1); + await fillRelay(spokePool, { ...deposit, originChainId: originChainId2 }, relayer1); + await fillRelay(spokePool, { ...deposit, inputAmount: deposit.inputAmount.add(bnOne) }, relayer1); + await fillRelay(spokePool, { ...deposit, inputAmount: deposit.outputAmount.sub(bnOne) }, relayer2); await spokePoolClient.update(); @@ -105,7 +105,7 @@ describe("SpokePoolClient: Fills", function () { for (let i = 0; i < nBlocks; ++i) { const blockNumber = await spokePool.provider.getBlockNumber(); if (blockNumber === targetFillBlock - 1) { - const { blockNumber: fillBlockNumber } = await fillV3Relay(spokePool, deposit, relayer1); + const { blockNumber: fillBlockNumber } = await fillRelay(spokePool, deposit, relayer1); expect(fillBlockNumber).to.equal(targetFillBlock); continue; } @@ -121,9 +121,9 @@ describe("SpokePoolClient: Fills", function () { const targetDeposit = { ...deposit, depositId: deposit.depositId.add(1) }; // Submit multiple fills at the same block: const startBlock = await spokePool.provider.getBlockNumber(); - await fillV3Relay(spokePool, deposit, relayer1); - await fillV3Relay(spokePool, targetDeposit, relayer1); - await fillV3Relay(spokePool, { ...deposit, depositId: deposit.depositId.add(2) }, relayer1); + await fillRelay(spokePool, deposit, relayer1); + await fillRelay(spokePool, targetDeposit, relayer1); + await fillRelay(spokePool, { ...deposit, depositId: deposit.depositId.add(2) }, relayer1); await hre.network.provider.send("evm_mine"); let fill = await findFillEvent(spokePool, targetDeposit, startBlock); @@ -148,7 +148,7 @@ describe("SpokePoolClient: Fills", function () { const fillBlock = await findFillBlock(spokePool, deposit, startBlock); expect(fillBlock).to.be.undefined; - const { blockNumber: lateBlockNumber } = await fillV3Relay(spokePool, deposit, relayer1); + const { blockNumber: lateBlockNumber } = await fillRelay(spokePool, deposit, relayer1); await hre.network.provider.send("evm_mine"); // Now search for the fill _after_ it was filled and expect an exception. From d1aaee98a31f08cf4da6e69cd6d4c280610f6732 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:18:39 +0000 Subject: [PATCH 08/13] Drop populateRelay --- src/utils/SpokeUtils.ts | 45 ----------------------------------------- 1 file changed, 45 deletions(-) diff --git a/src/utils/SpokeUtils.ts b/src/utils/SpokeUtils.ts index a4119ac7f..941b6cc08 100644 --- a/src/utils/SpokeUtils.ts +++ b/src/utils/SpokeUtils.ts @@ -14,51 +14,6 @@ import { toBytes32 } from "./AddressUtils"; type BlockTag = providers.BlockTag; -/** - * @param spokePool SpokePool Contract instance. - * @param deposit Deopsit instance. - * @param repaymentChainId Optional repaymentChainId (defaults to destinationChainId). - * @returns An Ethers UnsignedTransaction instance. - */ -export function populateRelay( - spokePool: Contract, - deposit: Omit, - relayer: string, - repaymentChainId = deposit.destinationChainId -): Promise { - const RelayData = { - depositor: toBytes32(deposit.depositor), - recipient: toBytes32(deposit.recipient), - exclusiveRelayer: toBytes32(deposit.exclusiveRelayer), - inputToken: toBytes32(deposit.inputToken), - outputToken: toBytes32(deposit.outputToken), - inputAmount: deposit.inputAmount, - outputAmount: deposit.outputAmount, - originChainId: deposit.originChainId, - depositId: deposit.depositId, - fillDeadline: deposit.fillDeadline, - exclusivityDeadline: deposit.exclusivityDeadline, - message: deposit.message, - }; - if (isDefined(deposit.speedUpSignature)) { - assert(isDefined(deposit.updatedRecipient) && !isZeroAddress(deposit.updatedRecipient)); - assert(isDefined(deposit.updatedOutputAmount)); - assert(isDefined(deposit.updatedMessage)); - return spokePool.populateTransaction.fillRelayWithUpdatedDeposit( - RelayData, - repaymentChainId, - toBytes32(relayer), - deposit.updatedOutputAmount, - toBytes32(deposit.updatedRecipient), - deposit.updatedMessage, - deposit.speedUpSignature, - { from: relayer } - ); - } - - return spokePool.populateTransaction.fillRelay(RelayData, repaymentChainId, toBytes32(relayer), { from: relayer }); -} - /** * @param spokePool SpokePool Contract instance. * @param deposit V3Deopsit instance. From b595838737a90bf24b7a2cb2e9051d2f4c608679 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:20:25 +0000 Subject: [PATCH 09/13] lint --- test/SpokePoolClient.ValidateFill.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SpokePoolClient.ValidateFill.ts b/test/SpokePoolClient.ValidateFill.ts index 4c63add08..1130cab2d 100644 --- a/test/SpokePoolClient.ValidateFill.ts +++ b/test/SpokePoolClient.ValidateFill.ts @@ -56,10 +56,10 @@ let spokePoolClient1: SpokePoolClient, configStoreClient: MockConfigStoreClient; describe("SpokePoolClient: Fill Validation", function () { const truncateAddresses = (relayData: Omit): void => { // Events emit bytes32 but the SpokePoolClient truncates evm addresses back to bytes20. - ["depositor", "recipient", "inputToken", "outputToken", "exclusiveRelayer"].forEach((field) => - relayData[field] = toAddress(relayData[field]) + ["depositor", "recipient", "inputToken", "outputToken", "exclusiveRelayer"].forEach( + (field) => (relayData[field] = toAddress(relayData[field])) ); - } + }; let inputToken: string, outputToken: string; let inputAmount: BigNumber, outputAmount: BigNumber; From 1a1e6c90920d493aeaf451f62690eac39b0a098b Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 28 Feb 2025 16:38:19 +0000 Subject: [PATCH 10/13] Restore legacy deposit search --- src/clients/SpokePoolClient.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/clients/SpokePoolClient.ts b/src/clients/SpokePoolClient.ts index c11a2e2b8..9c964abce 100644 --- a/src/clients/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient.ts @@ -935,13 +935,25 @@ export class SpokePoolClient extends BaseAbstractClient { ); const tStart = Date.now(); + // Check both V3FundsDeposited and FundsDeposited events to look for a specified depositId. + // This must be retained for the forseeable future because older V3FundsDeposited events with infinite + // expiry might still exist and be filled in future. const [fromBlock, toBlock] = [searchBounds.low, searchBounds.high]; const { maxBlockLookBack } = this.eventSearchConfig; - const query = await paginatedEventQuery( - this.spokePool, - this.spokePool.filters.FundsDeposited(null, null, null, null, null, depositId), - { fromBlock, toBlock, maxBlockLookBack } - ); + const query = ( + await Promise.all([ + paginatedEventQuery( + this.spokePool, + this.spokePool.filters.V3FundsDeposited(null, null, null, null, null, depositId), + { fromBlock, toBlock, maxBlockLookBack } + ), + paginatedEventQuery( + this.spokePool, + this.spokePool.filters.FundsDeposited(null, null, null, null, null, depositId), + { fromBlock, toBlock, maxBlockLookBack } + ), + ]) + ).flat(); const tStop = Date.now(); const event = query.find(({ args }) => args["depositId"].eq(depositId)); From 342b419758dd8e2e7b169ba766c3cc9d66b3ecfe Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:41:53 +0000 Subject: [PATCH 11/13] Fix test --- test/SpokePoolClient.ValidateFill.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SpokePoolClient.ValidateFill.ts b/test/SpokePoolClient.ValidateFill.ts index 7e56d0a35..3f2960f2b 100644 --- a/test/SpokePoolClient.ValidateFill.ts +++ b/test/SpokePoolClient.ValidateFill.ts @@ -538,7 +538,7 @@ describe("SpokePoolClient: Fill Validation", function () { } }); - it.only("Can fetch younger deposit matching fill", async function () { + it("Can fetch younger deposit matching fill", async function () { const depositEvent = await deposit( spokePool_1, destinationChainId, @@ -554,8 +554,8 @@ describe("SpokePoolClient: Fill Validation", function () { await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); - // Set event search config to block to before deposit so client doesn't see event. - spokePoolClient1.firstBlockToSearch = depositBlock - 1; + // Set event search config to block to after deposit so client doesn't see event. + spokePoolClient1.firstBlockToSearch = depositBlock + 1; await spokePoolClient1.update(); // Make sure that the client's latestBlockSearched encompasses the event so it can see it on the subsequent From 8cba4f8fef5242b764cd541b35085d1b424b86e8 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:52:01 +0000 Subject: [PATCH 12/13] Fix 2nd test --- test/SpokePoolClient.fills.ts | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/test/SpokePoolClient.fills.ts b/test/SpokePoolClient.fills.ts index 4e651eac6..f609840f1 100644 --- a/test/SpokePoolClient.fills.ts +++ b/test/SpokePoolClient.fills.ts @@ -16,7 +16,7 @@ import { originChainId, destinationChainId } from "./constants"; import { assertPromiseError, Contract, - depositV3, + deposit, SignerWithAddress, fillRelay, createSpyLogger, @@ -35,7 +35,7 @@ describe("SpokePoolClient: Fills", function () { let depositor: SignerWithAddress, relayer1: SignerWithAddress, relayer2: SignerWithAddress; let spokePoolClient: SpokePoolClient; let deploymentBlock: number; - let deposit: Deposit; + let depositTemplate: Deposit; beforeEach(async function () { [, depositor, relayer1, relayer2] = await ethers.getSigners(); @@ -62,7 +62,7 @@ describe("SpokePoolClient: Fills", function () { const outputAmount = toBNWei(1); const message = EMPTY_MESSAGE; - deposit = { + depositTemplate = { depositId: bnZero, originChainId, destinationChainId, @@ -84,18 +84,18 @@ describe("SpokePoolClient: Fills", function () { }); it("Correctly fetches fill data single fill, single chain", async function () { - await fillRelay(spokePool, deposit, relayer1); - await fillRelay(spokePool, { ...deposit, depositId: deposit.depositId.add(1) }, relayer1); + await fillRelay(spokePool, depositTemplate, relayer1); + await fillRelay(spokePool, { ...depositTemplate, depositId: depositTemplate.depositId.add(1) }, relayer1); await spokePoolClient.update(); expect(spokePoolClient.getFills().length).to.equal(2); }); it("Correctly fetches deposit data multiple fills, multiple chains", async function () { // Mix and match various fields to produce unique fills and verify they are all recorded by the SpokePoolClient. - await fillRelay(spokePool, deposit, relayer1); - await fillRelay(spokePool, { ...deposit, originChainId: originChainId2 }, relayer1); - await fillRelay(spokePool, { ...deposit, inputAmount: deposit.inputAmount.add(bnOne) }, relayer1); - await fillRelay(spokePool, { ...deposit, inputAmount: deposit.outputAmount.sub(bnOne) }, relayer2); + await fillRelay(spokePool, depositTemplate, relayer1); + await fillRelay(spokePool, { ...depositTemplate, originChainId: originChainId2 }, relayer1); + await fillRelay(spokePool, { ...depositTemplate, inputAmount: depositTemplate.inputAmount.add(bnOne) }, relayer1); + await fillRelay(spokePool, { ...depositTemplate, inputAmount: depositTemplate.outputAmount.sub(bnOne) }, relayer2); await spokePoolClient.update(); @@ -123,7 +123,7 @@ describe("SpokePoolClient: Fills", function () { const inputAmount = bnOne; const outputToken = ZERO_ADDRESS; const outputAmount = bnOne; - const { depositId: _depositId, blockNumber: depositBlockNumber } = await depositV3( + const { depositId: _depositId, blockNumber: depositBlockNumber } = await deposit( spokePool, destinationChainId, relayer1, @@ -156,7 +156,7 @@ describe("SpokePoolClient: Fills", function () { for (let i = 0; i < nBlocks; ++i) { const blockNumber = await spokePool.provider.getBlockNumber(); if (blockNumber === targetFillBlock - 1) { - const { blockNumber: fillBlockNumber } = await fillRelay(spokePool, deposit, relayer1); + const { blockNumber: fillBlockNumber } = await fillRelay(spokePool, depositTemplate, relayer1); expect(fillBlockNumber).to.equal(targetFillBlock); continue; } @@ -164,17 +164,17 @@ describe("SpokePoolClient: Fills", function () { await hre.network.provider.send("evm_mine"); } - const fillBlock = await findFillBlock(spokePool, deposit, startBlock); + const fillBlock = await findFillBlock(spokePool, depositTemplate, startBlock); expect(fillBlock).to.equal(targetFillBlock); }); it("Correctly returns a Fill event using the relay data", async function () { - const targetDeposit = { ...deposit, depositId: deposit.depositId.add(1) }; + const targetDeposit = { ...depositTemplate, depositId: depositTemplate.depositId.add(1) }; // Submit multiple fills at the same block: const startBlock = await spokePool.provider.getBlockNumber(); - await fillRelay(spokePool, deposit, relayer1); + await fillRelay(spokePool, depositTemplate, relayer1); await fillRelay(spokePool, targetDeposit, relayer1); - await fillRelay(spokePool, { ...deposit, depositId: deposit.depositId.add(2) }, relayer1); + await fillRelay(spokePool, { ...depositTemplate, depositId: depositTemplate.depositId.add(2) }, relayer1); await hre.network.provider.send("evm_mine"); let fill = await findFillEvent(spokePool, targetDeposit, startBlock); @@ -184,7 +184,7 @@ describe("SpokePoolClient: Fills", function () { expect(fill.depositId).to.equal(targetDeposit.depositId); // Looking for a fill can return undefined: - const missingFill = await findFillEvent(spokePool, { ...deposit, depositId: deposit.depositId.add(3) }, startBlock); + const missingFill = await findFillEvent(spokePool, { ...depositTemplate, depositId: depositTemplate.depositId.add(3) }, startBlock); expect(missingFill).to.be.undefined; }); @@ -207,7 +207,7 @@ describe("SpokePoolClient: Fills", function () { const outputToken = ZERO_ADDRESS; const outputAmount = bnOne; - const { depositId, blockNumber } = await depositV3( + const { depositId, blockNumber } = await deposit( spokePool, destinationChainId, relayer1, @@ -239,22 +239,22 @@ describe("SpokePoolClient: Fills", function () { } // No fill has been made, so expect an undefined fillBlock. - const fillBlock = await findFillBlock(spokePool, deposit, startBlock); + const fillBlock = await findFillBlock(spokePool, depositTemplate, startBlock); expect(fillBlock).to.be.undefined; - const { blockNumber: lateBlockNumber } = await fillRelay(spokePool, deposit, relayer1); + const { blockNumber: lateBlockNumber } = await fillRelay(spokePool, depositTemplate, relayer1); await hre.network.provider.send("evm_mine"); // Now search for the fill _after_ it was filled and expect an exception. - const srcChain = getNetworkName(deposit.originChainId); + const srcChain = getNetworkName(depositTemplate.originChainId); await assertPromiseError( - findFillBlock(spokePool, deposit, lateBlockNumber), - `${srcChain} deposit ${deposit.depositId.toString()} filled on ` + findFillBlock(spokePool, depositTemplate, lateBlockNumber), + `${srcChain} deposit ${depositTemplate.depositId.toString()} filled on ` ); // Should assert if highBlock <= lowBlock. await assertPromiseError( - findFillBlock(spokePool, deposit, await spokePool.provider.getBlockNumber()), + findFillBlock(spokePool, depositTemplate, await spokePool.provider.getBlockNumber()), "Block numbers out of range" ); }); From a24d90263ace7bbbb4fd72098843f4876c87bbe7 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:57:17 +0000 Subject: [PATCH 13/13] lint --- test/SpokePoolClient.fills.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/SpokePoolClient.fills.ts b/test/SpokePoolClient.fills.ts index f609840f1..933b4e577 100644 --- a/test/SpokePoolClient.fills.ts +++ b/test/SpokePoolClient.fills.ts @@ -184,7 +184,11 @@ describe("SpokePoolClient: Fills", function () { expect(fill.depositId).to.equal(targetDeposit.depositId); // Looking for a fill can return undefined: - const missingFill = await findFillEvent(spokePool, { ...depositTemplate, depositId: depositTemplate.depositId.add(3) }, startBlock); + const missingFill = await findFillEvent( + spokePool, + { ...depositTemplate, depositId: depositTemplate.depositId.add(3) }, + startBlock + ); expect(missingFill).to.be.undefined; });