Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(Dataworker): Support pre-fill refunds and duplicate deposits #2010

Merged
merged 77 commits into from
Feb 3, 2025
Merged
Changes from 1 commit
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
e4d8275
feat(Dataworker): Support pre-fill refunds
nicholaspai Jan 23, 2025
fbb6147
Finish new tests
nicholaspai Jan 23, 2025
40ad15f
Update Dataworker.buildRoots.ts
nicholaspai Jan 23, 2025
cc956ac
Revert "Update Dataworker.buildRoots.ts"
nicholaspai Jan 23, 2025
b099cf0
Add test against duplicate deposits
nicholaspai Jan 23, 2025
3d4097d
Add unit tests for duplicate deposits
nicholaspai Jan 24, 2025
12673d8
Import beta sdk
nicholaspai Jan 24, 2025
79e8490
Merge branch 'master' into prefills
nicholaspai Jan 24, 2025
b7bf412
import sdk
nicholaspai Jan 24, 2025
1454f10
update import
nicholaspai Jan 24, 2025
8879124
Update package.json
nicholaspai Jan 24, 2025
6ffc950
Update config.yml
nicholaspai Jan 24, 2025
6e78182
wip
nicholaspai Jan 24, 2025
bc1669d
Fix tests
nicholaspai Jan 24, 2025
7f32c08
Update SpokePoolUtils.ts
nicholaspai Jan 24, 2025
9cd9007
Update SpokePoolUtils.ts
nicholaspai Jan 24, 2025
81e2ab4
Merge branch 'master' into prefills
nicholaspai Jan 24, 2025
284b243
Update Dataworker.loadData.prefill.ts
nicholaspai Jan 24, 2025
e203452
Merge branch 'master' into prefills
nicholaspai Jan 24, 2025
fdc2c87
Merge branch 'master' into prefills
nicholaspai Jan 24, 2025
68890bd
Add tests for zero value deposits
nicholaspai Jan 26, 2025
f3c5dd3
Merge branch 'master' into prefills
nicholaspai Jan 27, 2025
bac9f3a
Merge branch 'master' into prefills
nicholaspai Jan 27, 2025
72d2560
Merge branch 'master' into prefills
nicholaspai Jan 27, 2025
75e35bc
Split up tests to speed up CI
nicholaspai Jan 27, 2025
16702f1
Merge branch 'master' into prefills
nicholaspai Jan 27, 2025
f1bbc6e
import
nicholaspai Jan 27, 2025
cc902c5
Update package.json
nicholaspai Jan 27, 2025
5bd8e3e
Update yarn.lock
nicholaspai Jan 27, 2025
496e1b6
import
nicholaspai Jan 27, 2025
de14a4e
Fix tests
nicholaspai Jan 28, 2025
512937d
fix
nicholaspai Jan 29, 2025
95fac03
bump
nicholaspai Jan 29, 2025
1f7f2cd
Remove mocked version bump in non-prefill tests
nicholaspai Jan 29, 2025
ce657f5
wip
nicholaspai Jan 29, 2025
b5252cf
lint
nicholaspai Jan 29, 2025
d11e982
bump
nicholaspai Jan 29, 2025
cc5ed3e
Merge branch 'master' into prefills
nicholaspai Jan 29, 2025
9949679
bump
nicholaspai Jan 29, 2025
c46bcd2
fix
nicholaspai Jan 29, 2025
959b57f
import
nicholaspai Jan 30, 2025
b385670
fix
nicholaspai Jan 30, 2025
7d8ea1f
Merge branch 'master' into prefills
nicholaspai Jan 30, 2025
4cbfc5d
Update Dataworker.loadData.fill.ts
nicholaspai Jan 30, 2025
92ff83e
Fix tests
nicholaspai Jan 30, 2025
70ac78a
move some bytes32 invalid test cases to pre-fills because they hit pr…
nicholaspai Jan 30, 2025
763e27c
WIP
nicholaspai Jan 30, 2025
e552381
Update Dataworker.loadData.prefill.ts
nicholaspai Jan 30, 2025
96007bf
update
nicholaspai Jan 30, 2025
135a744
Merge branch 'master' into prefills
nicholaspai Jan 30, 2025
3f43367
WIP
nicholaspai Jan 30, 2025
f25b7c4
fix
nicholaspai Jan 30, 2025
18a2b9d
wip
nicholaspai Jan 31, 2025
649c5f3
update
nicholaspai Jan 31, 2025
43d73f5
fix
nicholaspai Jan 31, 2025
6c6c3d4
Merge branch 'master' into prefills
nicholaspai Jan 31, 2025
2694774
Update Dataworker.loadData.prefill.ts
nicholaspai Jan 31, 2025
8e3c775
fix
nicholaspai Jan 31, 2025
3bfc2e1
bump package to new duplicate refund version
nicholaspai Jan 31, 2025
e9c384d
Add test cases for historical deposit query when matched deposit is i…
nicholaspai Jan 31, 2025
9540e81
fix
nicholaspai Jan 31, 2025
5b060b1
Update Dataworker.loadData.fill.ts
nicholaspai Jan 31, 2025
a485768
Update Dataworker.loadData.fill.ts
nicholaspai Jan 31, 2025
45aa837
pay refunds to pre-filler unless slow fill
nicholaspai Jan 31, 2025
0f44c36
Update Dataworker.loadData.prefill.ts
nicholaspai Jan 31, 2025
5961af9
Update Dataworker.loadData.prefill.ts
nicholaspai Jan 31, 2025
2ee3df9
Merge branch 'master' into prefills
nicholaspai Jan 31, 2025
2e761eb
fix
nicholaspai Jan 31, 2025
6579181
Add verifyFillRepayment test for pre fills
nicholaspai Feb 1, 2025
f003ad5
add asserts
nicholaspai Feb 2, 2025
5532611
wip
nicholaspai Feb 3, 2025
dc1efcf
Merge branch 'master' into prefills
nicholaspai Feb 3, 2025
a9a4b5a
34
nicholaspai Feb 3, 2025
db032e7
fix test
nicholaspai Feb 3, 2025
a92ac5e
4.0.0
nicholaspai Feb 3, 2025
49538ee
Update Constants.ts
nicholaspai Feb 3, 2025
9476bc0
Merge branch 'master' into prefills
nicholaspai Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(Dataworker): Support pre-fill refunds
This PR should be backwards compatible and deployable to production today

to be paired with across-protocol/sdk#835
nicholaspai committed Jan 23, 2025
commit e4d82753649ead7939613c06a164eefb8f3cfc45
29 changes: 22 additions & 7 deletions test/Dataworker.loadData.fill.ts
Original file line number Diff line number Diff line change
@@ -590,9 +590,18 @@ describe("Dataworker: Load data used in all functions", async function () {
expect(data1.bundleDepositsV3).to.deep.equal({});
});
it("Filters fills out of block range", async function () {
generateV3Deposit({ outputToken: randomAddress() });
generateV3Deposit({ outputToken: randomAddress() });
generateV3Deposit({ outputToken: randomAddress() });
generateV3Deposit({
outputToken: randomAddress(),
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 1,
});
generateV3Deposit({
outputToken: randomAddress(),
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 11,
});
generateV3Deposit({
outputToken: randomAddress(),
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 21,
});
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

@@ -607,13 +616,16 @@ describe("Dataworker: Load data used in all functions", async function () {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber + 21,
}),
];
// Create a block range that contains only the middle event.
// Create a block range that contains only the middle events.
const destinationChainBlockRange = [fills[1].blockNumber - 1, fills[1].blockNumber + 1];
// Substitute destination chain bundle block range.
const originChainBlockRange = [deposits[1].blockNumber - 1, deposits[1].blockNumber + 1];
// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = destinationChainBlockRange;
const originChainIndex = dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(originChainId);
bundleBlockRanges[originChainIndex] = originChainBlockRange;
await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
expect(mockDestinationSpokePoolClient.getFills().length).to.equal(fills.length);
const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
@@ -725,8 +737,11 @@ describe("Dataworker: Load data used in all functions", async function () {

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(blockRanges, spokePoolClients);
expect(data1.bundleDepositsV3).to.deep.equal({});
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.length).to.equal(1);
expect(spyLogIncludes(spy, -2, "invalid V3 fills in range")).to.be.false;

// Fill should not be included since we cannot validate fills when the deposit is in a following bundle.
// This fill is considered a "pre-fill" and will be validated when the deposit is included in a bundle.
expect(data1.bundleFillsV3).to.deep.equal({});
expect(spyLogIncludes(spy, -2, "invalid V3 fills in range")).to.be.true;
});
it("Does not count prior bundle expired deposits that were filled", async function () {
// Send deposit that expires in this bundle.
331 changes: 331 additions & 0 deletions test/Dataworker.loadData.prefill.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
import { BundleDataClient, ConfigStoreClient, HubPoolClient, SpokePoolClient } from "../src/clients";
import { destinationChainId, originChainId, repaymentChainId } from "./constants";
import { setupDataworker } from "./fixtures/Dataworker.Fixture";
import {
Contract,
FakeContract,
SignerWithAddress,
V3FillFromDeposit,
ethers,
expect,
getDefaultBlockRange,
randomAddress,
smock,
} from "./utils";

import { Dataworker } from "../src/dataworker/Dataworker"; // Tested
import { getCurrentTime, Event, toBNWei, ZERO_ADDRESS } from "../src/utils";
import { MockHubPoolClient, MockSpokePoolClient } from "./mocks";
import { interfaces } from "@across-protocol/sdk";

let erc20_1: Contract, erc20_2: Contract;
let l1Token_1: Contract;
let relayer: SignerWithAddress;

let spokePoolClient_1: SpokePoolClient, spokePoolClient_2: SpokePoolClient;
let hubPoolClient: HubPoolClient, configStoreClient: ConfigStoreClient;
let dataworkerInstance: Dataworker;
let spokePoolClients: { [chainId: number]: SpokePoolClient };

let updateAllClients: () => Promise<void>;

describe("BundleDataClient: Pre-fill logic", async function () {
beforeEach(async function () {
({
erc20_1,
erc20_2,
hubPoolClient,
configStoreClient,
l1Token_1,
relayer,
dataworkerInstance,
spokePoolClient_1,
spokePoolClient_2,
spokePoolClients,
updateAllClients,
} = await setupDataworker(ethers, 25, 25, 0));
});

describe("loadDataFromScratch", function () {
let mockOriginSpokePoolClient: MockSpokePoolClient, mockDestinationSpokePoolClient: MockSpokePoolClient;
let mockHubPoolClient: MockHubPoolClient;
let mockDestinationSpokePool: FakeContract;
const lpFeePct = toBNWei("0.01");

beforeEach(async function () {
await updateAllClients();
mockHubPoolClient = new MockHubPoolClient(
hubPoolClient.logger,
hubPoolClient.hubPool,
configStoreClient,
hubPoolClient.deploymentBlock,
hubPoolClient.chainId
);
// Mock a realized lp fee pct for each deposit so we can check refund amounts and bundle lp fees.
mockHubPoolClient.setDefaultRealizedLpFeePct(lpFeePct);
mockOriginSpokePoolClient = new MockSpokePoolClient(
spokePoolClient_1.logger,
spokePoolClient_1.spokePool,
spokePoolClient_1.chainId,
spokePoolClient_1.deploymentBlock
);
mockDestinationSpokePool = await smock.fake(spokePoolClient_2.spokePool.interface);
mockDestinationSpokePoolClient = new MockSpokePoolClient(
spokePoolClient_2.logger,
mockDestinationSpokePool as Contract,
spokePoolClient_2.chainId,
spokePoolClient_2.deploymentBlock
);
spokePoolClients = {
...spokePoolClients,
[originChainId]: mockOriginSpokePoolClient,
[destinationChainId]: mockDestinationSpokePoolClient,
};
await mockHubPoolClient.update();
await mockOriginSpokePoolClient.update();
await mockDestinationSpokePoolClient.update();
mockHubPoolClient.setTokenMapping(l1Token_1.address, originChainId, erc20_1.address);
mockHubPoolClient.setTokenMapping(l1Token_1.address, destinationChainId, erc20_2.address);
mockHubPoolClient.setTokenMapping(l1Token_1.address, repaymentChainId, l1Token_1.address);
const bundleDataClient = new BundleDataClient(
dataworkerInstance.logger,
{
...dataworkerInstance.clients.bundleDataClient.clients,
hubPoolClient: mockHubPoolClient as unknown as HubPoolClient,
},
dataworkerInstance.clients.bundleDataClient.spokePoolClients,
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers
);
dataworkerInstance = new Dataworker(
dataworkerInstance.logger,
{ ...dataworkerInstance.clients, bundleDataClient },
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers,
dataworkerInstance.maxRefundCountOverride,
dataworkerInstance.maxL1TokenCountOverride,
dataworkerInstance.blockRangeEndBlockBuffer
);
});

function generateV3Deposit(eventOverride?: Partial<interfaces.DepositWithBlock>): Event {
return mockOriginSpokePoolClient.depositV3({
inputToken: erc20_1.address,
outputToken: eventOverride?.outputToken ?? erc20_2.address,
message: "0x",
quoteTimestamp: eventOverride?.quoteTimestamp ?? getCurrentTime() - 10,
fillDeadline: eventOverride?.fillDeadline ?? getCurrentTime() + 14400,
destinationChainId,
blockNumber: eventOverride?.blockNumber ?? spokePoolClient_1.latestBlockSearched, // @dev use latest block searched from non-mocked client
// so that mocked client's latestBlockSearched gets set to the same value.
} as interfaces.DepositWithBlock);
}

function generateV3FillFromDeposit(
deposit: interfaces.DepositWithBlock,
fillEventOverride?: Partial<interfaces.FillWithBlock>,
_relayer = relayer.address,
_repaymentChainId = repaymentChainId,
fillType = interfaces.FillType.FastFill
): Event {
const fillObject = V3FillFromDeposit(deposit, _relayer, _repaymentChainId);
return mockDestinationSpokePoolClient.fillV3Relay({
...fillObject,
relayExecutionInfo: {
updatedRecipient: fillObject.updatedRecipient,
updatedMessage: fillObject.updatedMessage,
updatedOutputAmount: fillObject.updatedOutputAmount,
fillType,
},
blockNumber: fillEventOverride?.blockNumber ?? spokePoolClient_2.latestBlockSearched, // @dev use latest block searched from non-mocked client
// so that mocked client's latestBlockSearched gets set to the same value.
} as interfaces.FillWithBlock);
}

function generateSlowFillRequestFromDeposit(
deposit: interfaces.DepositWithBlock,
fillEventOverride?: Partial<interfaces.FillWithBlock>
): Event {
const fillObject = V3FillFromDeposit(deposit, ZERO_ADDRESS);
const { relayer, repaymentChainId, relayExecutionInfo, ...relayData } = fillObject;
return mockDestinationSpokePoolClient.requestV3SlowFill({
...relayData,
blockNumber: fillEventOverride?.blockNumber ?? spokePoolClient_2.latestBlockSearched, // @dev use latest block searched from non-mocked client
// so that mocked client's latestBlockSearched gets set to the same value.
} as interfaces.SlowFillRequest);
}

describe("Pre-fills", function () {
it("Refunds fill if fill is in-memory and in older bundle", async function () {
generateV3Deposit({ outputToken: randomAddress() });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit fill that we won't include in the bundle block range.
const fill = generateV3FillFromDeposit(deposits[0], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber,
});
// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [fill.blockNumber + 1, fill.blockNumber + 2];

await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
expect(mockDestinationSpokePoolClient.getFills().length).to.equal(1);

// So, one of the fills is a pre-fill because its earlier than the bundle block range. Because its corresponding
// deposit is in the block range, we should refund it.
const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.length).to.equal(1);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills[0].depositId).to.equal(
fill.args.depositId
);
});

it("Does not refund fill if fill is in-memory but in a future bundle", async function () {
generateV3Deposit({ outputToken: randomAddress() });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit fill that we won't include in the bundle block range but is in a future bundle
const futureFill = generateV3FillFromDeposit(deposits[0], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber + 11,
});

// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [futureFill.blockNumber - 2, futureFill.blockNumber - 1];

await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
expect(mockDestinationSpokePoolClient.getFills().length).to.equal(1);

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleFillsV3).to.deep.equal({});
});

it("Does not refund fill if fill is in-memory but its a SlowFill", async function () {
generateV3Deposit({ outputToken: randomAddress() });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit fill in an older bundle but its a Slow Fill execution.
const slowFill = generateV3FillFromDeposit(
deposits[0],
{ blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber },
undefined,
undefined,
interfaces.FillType.SlowFill
);

// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [slowFill.blockNumber + 1, slowFill.blockNumber + 2];

await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
expect(mockDestinationSpokePoolClient.getFills().length).to.equal(1);

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleFillsV3).to.deep.equal({});
});

it("Refunds fill if fill status is Filled", async function () {
// Checks relayStatuses() for fill status
// Loads old event and sets refund address and repayment chain correctly.
});

it("Does not refund if fill status is not Filled", async function () {});
});

describe.only("Pre-slow-fill-requests", function () {
it("Creates slow fill leaf if slow fill request is in-memory and in older bundle", async function () {
generateV3Deposit({ outputToken: erc20_2.address });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit request that we won't include in the bundle block range.
const request = generateSlowFillRequestFromDeposit(deposits[0], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber,
});
// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [request.blockNumber + 1, request.blockNumber + 2];

await mockDestinationSpokePoolClient.update(["RequestedV3SlowFill"]);
expect(mockDestinationSpokePoolClient.getSlowFillRequestsForOriginChain(originChainId).length).to.equal(1);

// So, one of the fills is a pre-fill because its earlier than the bundle block range. Because its corresponding
// deposit is in the block range, we should refund it.
const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleSlowFillsV3[destinationChainId][erc20_2.address].length).to.equal(1);
expect(data1.bundleSlowFillsV3[destinationChainId][erc20_2.address][0].depositId).to.equal(
request.args.depositId
);
});

it("Creates slow fill leaf if fill status is RequestedSlowFill", async function () {
// Checks relayStatuses() for fill status
// Creates slow fill leaf.
});

it("Does not create slow fill leaf if slow fill request is in-memory but in a future bundle", async function () {
generateV3Deposit({ outputToken: erc20_2.address });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit request that we won't include in the bundle block range but is in a future bundle
const request = generateSlowFillRequestFromDeposit(deposits[0], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber + 11,
});

// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [request.blockNumber - 2, request.blockNumber - 1];

await mockDestinationSpokePoolClient.update(["RequestedV3SlowFill"]);
expect(mockDestinationSpokePoolClient.getSlowFillRequestsForOriginChain(originChainId).length).to.equal(1);

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleSlowFillsV3).to.deep.equal({});
});

it("Does not create slow fill leaf if slow fill request is in-memory but an invalid request", async function () {
generateV3Deposit({ outputToken: randomAddress() });
generateV3Deposit({ outputToken: erc20_2.address, fillDeadline: 0 });
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Submit request that that is in a previous bundle but is invalid.
generateSlowFillRequestFromDeposit(deposits[0], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber,
});
const expiredDepositRequest = generateSlowFillRequestFromDeposit(deposits[1], {
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber,
});

// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = [
expiredDepositRequest.blockNumber + 1,
expiredDepositRequest.blockNumber + 2,
];

await mockDestinationSpokePoolClient.update(["RequestedV3SlowFill"]);
expect(mockDestinationSpokePoolClient.getSlowFillRequestsForOriginChain(originChainId).length).to.equal(2);

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);
expect(data1.bundleSlowFillsV3).to.deep.equal({});
});

it("Does not create slow fill leaf if fill status is not RequestedSlowFill", async function () {});
});
});
});
22 changes: 17 additions & 5 deletions test/Dataworker.loadData.slowFill.ts
Original file line number Diff line number Diff line change
@@ -463,9 +463,18 @@ describe("BundleDataClient: Slow fill handling & validation", async function ()
});

it("Handles slow fill requests out of block range", async function () {
generateV3Deposit({ outputToken: erc20_2.address });
generateV3Deposit({ outputToken: erc20_2.address });
generateV3Deposit({ outputToken: erc20_2.address });
generateV3Deposit({
outputToken: erc20_2.address,
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 1,
});
generateV3Deposit({
outputToken: erc20_2.address,
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 11,
});
generateV3Deposit({
outputToken: erc20_2.address,
blockNumber: mockOriginSpokePoolClient.eventManager.blockNumber + 21,
});
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

@@ -480,13 +489,16 @@ describe("BundleDataClient: Slow fill handling & validation", async function ()
blockNumber: mockDestinationSpokePoolClient.eventManager.blockNumber + 21,
}),
];
// Create a block range that contains only the middle event.
// Create a block range that contains only the middle events.
const destinationChainBlockRange = [events[1].blockNumber - 1, events[1].blockNumber + 1];
// Substitute destination chain bundle block range.
const originChainBlockRange = [deposits[1].blockNumber - 1, deposits[1].blockNumber + 1];
// Substitute bundle block ranges.
const bundleBlockRanges = getDefaultBlockRange(5);
const destinationChainIndex =
dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(destinationChainId);
bundleBlockRanges[destinationChainIndex] = destinationChainBlockRange;
const originChainIndex = dataworkerInstance.chainIdListForBundleEvaluationBlockNumbers.indexOf(originChainId);
bundleBlockRanges[originChainIndex] = originChainBlockRange;
await mockDestinationSpokePoolClient.update(["RequestedV3SlowFill"]);
expect(mockDestinationSpokePoolClient.getSlowFillRequestsForOriginChain(originChainId).length).to.equal(3);
const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(bundleBlockRanges, spokePoolClients);