diff --git a/src/clients/SpokePoolClient/EVMSpokePoolClient.ts b/src/clients/SpokePoolClient/EVMSpokePoolClient.ts index 51da9d40c..38528b58a 100644 --- a/src/clients/SpokePoolClient/EVMSpokePoolClient.ts +++ b/src/clients/SpokePoolClient/EVMSpokePoolClient.ts @@ -206,7 +206,7 @@ export class EVMSpokePoolClient extends SpokePoolClient { 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, }); diff --git a/src/clients/SpokePoolClient/SpokePoolClient.ts b/src/clients/SpokePoolClient/SpokePoolClient.ts index eefe19b56..73b871113 100644 --- a/src/clients/SpokePoolClient/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient/SpokePoolClient.ts @@ -300,9 +300,10 @@ export abstract 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]; } @@ -553,7 +554,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient { } }; - for (const event of ["V3FundsDeposited", "FundsDeposited"]) { + for (const event of ["FundsDeposited"]) { if (eventsToQuery.includes(event)) { await queryDepositEvents(event); } @@ -581,7 +582,7 @@ export abstract 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); } @@ -596,10 +597,6 @@ export abstract class SpokePoolClient extends BaseAbstractClient { destinationChainId: this.chainId, }; - if (eventName === "RequestedV3SlowFill") { - slowFillRequest.messageHash = getMessageHash(slowFillRequest.message); - } - const depositHash = getRelayEventKey({ ...slowFillRequest, destinationChainId: this.chainId }); // Sanity check that this event is not a duplicate. @@ -612,7 +609,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient { } }; - ["RequestedV3SlowFill", "RequestedSlowFill"].forEach((event) => { + ["RequestedSlowFill"].forEach((event) => { if (eventsToQuery.includes(event)) { queryRequestedSlowFillEvents(event); } @@ -636,11 +633,6 @@ export abstract class SpokePoolClient extends BaseAbstractClient { destinationChainId: this.chainId, }; - if (eventName === "FilledV3Relay") { - fill.messageHash = getMessageHash((event as unknown as { message: string }).message); - fill.relayExecutionInfo.updatedMessageHash = getMessageHash(event.relayExecutionInfo.updatedMessage!); - } - // Sanity check that this event is not a duplicate. const duplicateFill = this.fills[fill.originChainId]?.find((f) => duplicateEvent(fill, f)); if (duplicateFill) { @@ -654,7 +646,7 @@ export abstract class SpokePoolClient extends BaseAbstractClient { }; // Update observed fills with ingested event data. - ["FilledV3Relay", "FilledRelay"].forEach((event) => { + ["FilledRelay"].forEach((event) => { if (eventsToQuery.includes(event)) { queryFilledRelayEvents(event); } diff --git a/src/clients/mocks/MockSpokePoolClient.ts b/src/clients/mocks/MockSpokePoolClient.ts index 5df3879b2..986aadd82 100644 --- a/src/clients/mocks/MockSpokePoolClient.ts +++ b/src/clients/mocks/MockSpokePoolClient.ts @@ -25,7 +25,6 @@ import { BigNumber, bnZero, bnOne, - toAddress, toBytes32, spreadEventWithBlockNumber, } from "../../utils"; @@ -85,6 +84,7 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { lastDepositId = _depositIds[i]; } } + _getDepositIdAtBlock(blockTag: number): Promise { return Promise.resolve(this.depositIdAtBlock[blockTag]); } @@ -129,10 +129,6 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { 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, txnIndex } = deposit; let { depositId, destinationChainId, inputAmount, outputAmount } = deposit; @@ -140,12 +136,11 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { 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")); @@ -180,17 +175,13 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { }); } - fillV3Relay(fill: Omit & { message: string } & Partial): Log { - return this._fillRelay("FilledV3Relay", fill); - } - - 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, txnIndex } = fill; let { originChainId, depositId, inputAmount, outputAmount, fillDeadline } = fill; @@ -200,15 +191,14 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { 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 topics = [originChainId, depositId, relayer]; const message = fill.message ?? EMPTY_MESSAGE; const updatedMessage = fill.relayExecutionInfo?.updatedMessage ?? message; @@ -239,25 +229,14 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { }, }; - 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, @@ -269,17 +248,12 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { }); } - 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 }; @@ -290,7 +264,7 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { args: { ...args, depositor, - updatedRecipient: addressModifier(speedUp.updatedRecipient), + updatedRecipient: toBytes32(speedUp.updatedRecipient), }, }); } @@ -308,24 +282,19 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { }); } - requestV3SlowFill(request: Omit & Partial): Log { - return this._requestSlowFill("RequestedV3SlowFill", request); - } - - requestSlowFill(request: Omit & Partial): Log { + requestSlowFill(request: Omit & Partial): Log { return this._requestSlowFill("RequestedSlowFill", request); } protected _requestSlowFill( event: string, - request: Omit & Partial + request: Omit & 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, @@ -333,20 +302,21 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { topics: topics.map((topic) => topic.toString()), args: { ...args, + destinationChainId: this.chainId, 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.txnIndex, }); } - // 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, @@ -361,7 +331,7 @@ export class MockSpokePoolClient extends EVMSpokePoolClient { }, }; - 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 1a2b2cbf1..a8887ee56 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; @@ -93,7 +90,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/test/SpokePoolClient.SpeedUp.ts b/test/SpokePoolClient.SpeedUp.ts index a283ffc45..e576dc774 100644 --- a/test/SpokePoolClient.SpeedUp.ts +++ b/test/SpokePoolClient.SpeedUp.ts @@ -10,7 +10,7 @@ import { createSpyLogger, deepEqualsWithBigNumber, deploySpokePoolWithToken, - depositV3, + deposit, ethers, expect, getUpdatedV3DepositSignature, @@ -57,7 +57,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, @@ -69,14 +69,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), @@ -87,7 +87,7 @@ describe("SpokePoolClient: SpeedUp", function () { .connect(depositor) .speedUpDeposit( toBytes32(depositor.address), - deposit.depositId, + depositEvent.depositId, updatedOutputAmount, toBytes32(updatedRecipient), updatedMessage, @@ -98,14 +98,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. @@ -120,7 +120,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, @@ -132,10 +132,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, @@ -175,13 +175,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; @@ -196,7 +196,7 @@ describe("SpokePoolClient: SpeedUp", function () { }); it("Ignores invalid updates", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool, destinationChainId, depositor, @@ -208,10 +208,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. @@ -232,7 +232,7 @@ describe("SpokePoolClient: SpeedUp", function () { const speedUp = spokePool .connect(depositor) - .speedUpV3Deposit( + .speedUpDeposit( testDepositor.address, testDepositId, updatedOutputAmount, @@ -246,9 +246,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 d79ed05c5..90831dea3 100644 --- a/test/SpokePoolClient.ValidateFill.ts +++ b/test/SpokePoolClient.ValidateFill.ts @@ -1,5 +1,5 @@ import hre from "hardhat"; -import { DepositWithBlock, FillStatus, FillType } from "../src/interfaces"; +import { DepositWithBlock, FillStatus, FillType, RelayData } from "../src/interfaces"; import { EVMSpokePoolClient, SpokePoolClient } from "../src/clients"; import { bnOne, @@ -8,6 +8,8 @@ import { InvalidFill, validateFillForDeposit, queryHistoricalDepositForFill, + toAddress, + toBytes32, deploy as deployMulticall, } from "../src/utils"; import { fillStatusArray, relayFillStatus } from "../src/arch/evm"; @@ -19,8 +21,8 @@ import { toBNWei, ethers, SignerWithAddress, - depositV3, - fillV3Relay, + deposit, + fillRelay, requestV3SlowFill, setupTokensForWallet, deploySpokePoolWithToken, @@ -48,6 +50,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; @@ -119,7 +128,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, @@ -128,10 +137,11 @@ 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 }); + truncateAddresses(fill); + expect(validateFillForDeposit(fill, depositEvent)).to.deep.equal({ valid: true }); const ignoredFields = [ "fromLiteChain", @@ -159,17 +169,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, @@ -179,19 +189,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); }); @@ -199,7 +209,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, @@ -208,7 +218,7 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - deposits.push(deposit); + deposits.push(depositEvent); } expect(deposits.length).to.be.greaterThan(0); @@ -217,7 +227,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); @@ -233,14 +243,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, @@ -249,21 +259,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, @@ -273,21 +283,23 @@ 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); + truncateAddresses(fill); + + expect(spokePoolClient2.getDepositForFill(fill)).to.not.exist; await spokePoolClient1.update(); - let 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("Can fetch older deposit matching fill", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -296,13 +308,12 @@ 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(); - // Set event search config from block to latest block so client doesn't see event. - spokePoolClient1.eventSearchConfig.from = await spokePool_1.provider.getBlockNumber(); - spokePoolClient1.firstHeightToSearch = spokePoolClient1.eventSearchConfig.from; + // Set event search config from block ahead of the deposit block so client doesn't see event. + spokePoolClient1.firstHeightToSearch = depositEvent.blockNumber + 1; await spokePoolClient1.update(); // Client has 0 deposits in memory so querying historical deposit sends fresh RPC requests. @@ -313,12 +324,12 @@ describe("SpokePoolClient: Fill Validation", function () { assert.equal(historicalDeposit.found, true, "Test is broken"); // tsc narrowing if (historicalDeposit.found) { - expect(historicalDeposit.deposit.depositId.eq(deposit.depositId)).to.be.true; + expect(historicalDeposit.deposit.depositId.eq(depositEvent.depositId)).to.be.true; } }); it("Can fetch younger deposit matching fill", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -327,14 +338,14 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - const { blockNumber: depositBlock } = deposit; + const { blockNumber: depositBlock } = depositEvent; - await fillV3Relay(spokePool_2, deposit, relayer); + await fillRelay(spokePool_2, depositEvent, relayer); await spokePoolClient2.update(); const [fill] = spokePoolClient2.getFills(); - // Set event search config to block to before deposit so client doesn't see event. - spokePoolClient1.eventSearchConfig.to = depositBlock - 1; + // Set event search config to block to after deposit so client doesn't see event. + spokePoolClient1.firstHeightToSearch = depositBlock + 1; await spokePoolClient1.update(); // Make sure that the client's latestBlockSearched encompasses the event so it can see it on the subsequent @@ -349,12 +360,12 @@ describe("SpokePoolClient: Fill Validation", function () { assert.equal(historicalDeposit.found, true, "Test is broken"); // tsc narrowing if (historicalDeposit.found) { - expect(historicalDeposit.deposit.depositId.eq(deposit.depositId)).to.be.true; + expect(historicalDeposit.deposit.depositId.eq(depositEvent.depositId)).to.be.true; } }); it("Loads fills from memory with deposit ID > SpokePoolClient's earliest deposit ID queried", async function () { - const deposit = await depositV3( + const depositEvent = await deposit( spokePool_1, destinationChainId, depositor, @@ -363,26 +374,25 @@ describe("SpokePoolClient: Fill Validation", function () { outputToken, outputAmount ); - await hre.network.provider.send("evm_mine"); await hre.network.provider.send("evm_mine"); // Configure the search range to skip the deposit. - spokePoolClient1.firstHeightToSearch = deposit.blockNumber + 1; + spokePoolClient1.firstHeightToSearch = depositEvent.blockNumber + 1; spokePoolClient1.eventSearchConfig.to = undefined; await spokePoolClient1.update(); // Client does not have the deposit and should search for it. - expect((await spokePoolClient1.findDeposit(deposit.depositId)).found).is.true; - expect(lastSpyLogIncludes(spy, "Located V3 deposit outside of SpokePoolClient's search range")).to.be.true; + expect((await spokePoolClient1.findDeposit(depositEvent.depositId)).found).is.true; + expect(lastSpyLogIncludes(spy, "Located deposit outside of SpokePoolClient's search range")).to.be.true; // Search the missing block range. spokePoolClient1.firstHeightToSearch = deposit.blockNumber - 1; await spokePoolClient1.update(); // Client has the deposit now; should not search. - expect((await spokePoolClient1.findDeposit(deposit.depositId)).found).is.true; - expect(lastSpyLogIncludes(spy, "Located V3 deposit outside of SpokePoolClient's search range")).to.be.false; + expect((await spokePoolClient1.findDeposit(depositEvent.depositId)).found).is.true; + expect(lastSpyLogIncludes(spy, "Located deposit outside of SpokePoolClient's search range")).to.be.false; }); it("Ignores fills with deposit ID < first deposit ID in spoke pool", async function () { @@ -396,7 +406,7 @@ describe("SpokePoolClient: Fill Validation", function () { }); it("Ignores fills with deposit ID > latest deposit ID in spoke pool", async function () { - await depositV3(spokePool_1, destinationChainId, depositor, inputToken, inputAmount, outputToken, outputAmount); + await deposit(spokePool_1, destinationChainId, depositor, inputToken, inputAmount, outputToken, outputAmount); const nextDepositId = await spokePool_1.numberOfDeposits(); await spokePoolClient1.update(); @@ -410,7 +420,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, @@ -420,8 +430,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()]); @@ -437,7 +447,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, @@ -448,39 +458,34 @@ 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 ); - // 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; - const deposit = spokePoolClient1.getDepositForFill(fill_1); - expect(deposit).to.exist; - let result = validateFillForDeposit(fill_1, deposit); + [fill_1, fill_2].forEach(truncateAddresses); + 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, @@ -489,43 +494,45 @@ 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); + truncateAddresses(fill); + 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/SpokePoolClient.fills.ts b/test/SpokePoolClient.fills.ts index 6bea07e90..124e88a08 100644 --- a/test/SpokePoolClient.fills.ts +++ b/test/SpokePoolClient.fills.ts @@ -8,9 +8,9 @@ import { originChainId, destinationChainId } from "./constants"; import { assertPromiseError, Contract, - depositV3, + deposit, SignerWithAddress, - fillV3Relay, + fillRelay, createSpyLogger, deploySpokePoolWithToken, ethers, @@ -27,7 +27,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(); @@ -54,7 +54,7 @@ describe("SpokePoolClient: Fills", function () { const outputAmount = toBNWei(1); const message = EMPTY_MESSAGE; - deposit = { + depositTemplate = { depositId: bnZero, originChainId, destinationChainId, @@ -76,18 +76,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, 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 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, 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(); @@ -115,7 +115,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, @@ -148,7 +148,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, depositTemplate, relayer1); expect(fillBlockNumber).to.equal(targetFillBlock); continue; } @@ -156,17 +156,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 fillV3Relay(spokePool, deposit, relayer1); - await fillV3Relay(spokePool, targetDeposit, relayer1); - await fillV3Relay(spokePool, { ...deposit, depositId: deposit.depositId.add(2) }, relayer1); + await fillRelay(spokePool, depositTemplate, relayer1); + await fillRelay(spokePool, targetDeposit, 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); @@ -176,7 +176,11 @@ 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; }); @@ -199,7 +203,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, @@ -231,22 +235,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 fillV3Relay(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" ); }); diff --git a/test/SpokePoolClient.v3Events.ts b/test/SpokePoolClient.v3Events.ts index fe31ec4bb..32a072fa9 100644 --- a/test/SpokePoolClient.v3Events.ts +++ b/test/SpokePoolClient.v3Events.ts @@ -2,17 +2,18 @@ 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, Log, SlowFillRequest, SpeedUp, TokensBridged } from "../src/interfaces"; import { - DepositWithBlock, - FillWithBlock, - Log, - SlowFillRequest, - SlowFillRequestWithBlock, - SpeedUp, - TokensBridged, -} from "../src/interfaces"; -import { bnOne, getCurrentTime, getMessageHash, isDefined, randomAddress, toAddress, toBN } from "../src/utils"; + bnOne, + getCurrentTime, + getMessageHash, + isDefined, + randomAddress, + toAddress, + toBytes32, + toBN, +} from "../src/utils"; import { SignerWithAddress, createSpyLogger, @@ -31,10 +32,10 @@ describe("SpokePoolClient: Event Filtering", function () { const randomBytes = (n: number): string => ethers.utils.hexlify(ethers.utils.randomBytes(n)); const destinationToken = randomAddress(); - 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[]; @@ -47,17 +48,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); @@ -69,7 +59,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 +120,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 +137,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 +151,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 +188,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 +233,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 +264,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 +278,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); }); @@ -301,13 +292,13 @@ describe("SpokePoolClient: Event Filtering", function () { const inputToken = randomAddress(); hubPoolClient.setDefaultRealizedLpFeePct(toBNWei("0.0001")); - const _deposit = spokePoolClient.depositV3({ + const _deposit = spokePoolClient.deposit({ originChainId, destinationChainId, inputToken, outputToken: ZERO_ADDRESS, } as DepositWithBlock); - expect(_deposit?.args?.outputToken).to.equal(ZERO_ADDRESS); + expect(_deposit?.args?.outputToken).to.equal(ZERO_BYTES); await spokePoolClient.update(fundsDepositedEvents); @@ -329,22 +320,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); @@ -352,54 +343,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)); } await destinationSpokePoolClient.update(filledRelayEvents); @@ -414,7 +404,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); }); }); @@ -436,14 +426,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!; @@ -460,8 +451,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!; @@ -475,7 +466,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, @@ -483,8 +474,9 @@ describe("SpokePoolClient: Event Filtering", function () { exclusiveRelayer, relayer, depositId: toBN(i), - } as FillWithBlock & { message: string }); - await originSpokePoolClient.update(["FilledV3Relay"]); + } as Omit); + await originSpokePoolClient.update(filledRelayEvents); + let relay = originSpokePoolClient.getFills().at(-1); expect(relay).to.exist; relay = relay!; @@ -502,7 +494,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, @@ -512,11 +504,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!; @@ -565,7 +558,7 @@ describe("SpokePoolClient: Event Filtering", function () { const relayExecutionInfo = { updatedRecipient, updatedOutputAmount: common.outputAmount, - updatedMessage: randomBytes(32), + updatedMessageHash: randomBytes(32), depositorSignature: randomBytes(32), }; @@ -608,8 +601,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, @@ -672,128 +665,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)); }); }); diff --git a/test/utils/utils.ts b/test/utils/utils.ts index 96c2a1086..38c700158 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -333,7 +333,7 @@ async function _deposit( await spokePool .connect(signer) - .depositV3( + .deposit( addressModifier(depositor), addressModifier(recipient), addressModifier(inputToken), @@ -420,7 +420,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, @@ -432,7 +431,7 @@ export async function requestV3SlowFill( }; } -export async function fillV3Relay( +export async function fillRelay( spokePool: Contract, deposit: Omit, signer: SignerWithAddress, @@ -463,20 +462,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,