@across-protocol/sdk 4.0.0-beta.33 → 4.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +4 -5
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +174 -336
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +2 -1
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +1 -5
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +1 -47
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
- package/dist/cjs/clients/SpokePoolClient.d.ts +0 -1
- package/dist/cjs/clients/SpokePoolClient.js +1 -10
- package/dist/cjs/clients/SpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSpokePoolClient.d.ts +1 -2
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js +1 -11
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/cjs/constants.d.ts +1 -1
- package/dist/cjs/constants.js +2 -2
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/providers/index.d.ts +0 -1
- package/dist/cjs/providers/index.js +0 -2
- package/dist/cjs/providers/index.js.map +1 -1
- package/dist/cjs/utils/AddressUtils.d.ts +0 -2
- package/dist/cjs/utils/AddressUtils.js +1 -19
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.d.ts +1 -2
- package/dist/cjs/utils/DepositUtils.js +1 -10
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/cjs/utils/EventUtils.js +0 -21
- package/dist/cjs/utils/EventUtils.js.map +1 -1
- package/dist/cjs/utils/NetworkUtils.d.ts +0 -1
- package/dist/cjs/utils/NetworkUtils.js +1 -6
- package/dist/cjs/utils/NetworkUtils.js.map +1 -1
- package/dist/cjs/utils/SpokeUtils.d.ts +0 -1
- package/dist/cjs/utils/SpokeUtils.js +8 -15
- package/dist/cjs/utils/SpokeUtils.js.map +1 -1
- package/dist/cjs/utils/common.d.ts +0 -1
- package/dist/cjs/utils/common.js +1 -2
- package/dist/cjs/utils/common.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +4 -5
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +256 -439
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +3 -2
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +1 -5
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +1 -54
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
- package/dist/esm/clients/SpokePoolClient.d.ts +0 -8
- package/dist/esm/clients/SpokePoolClient.js +1 -17
- package/dist/esm/clients/SpokePoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSpokePoolClient.d.ts +1 -2
- package/dist/esm/clients/mocks/MockSpokePoolClient.js +1 -11
- package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/esm/constants.d.ts +1 -1
- package/dist/esm/constants.js +2 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/providers/index.d.ts +0 -1
- package/dist/esm/providers/index.js +0 -2
- package/dist/esm/providers/index.js.map +1 -1
- package/dist/esm/utils/AddressUtils.d.ts +0 -2
- package/dist/esm/utils/AddressUtils.js +0 -25
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.d.ts +1 -2
- package/dist/esm/utils/DepositUtils.js +2 -11
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/esm/utils/EventUtils.js +1 -29
- package/dist/esm/utils/EventUtils.js.map +1 -1
- package/dist/esm/utils/NetworkUtils.d.ts +0 -6
- package/dist/esm/utils/NetworkUtils.js +0 -10
- package/dist/esm/utils/NetworkUtils.js.map +1 -1
- package/dist/esm/utils/SpokeUtils.d.ts +0 -1
- package/dist/esm/utils/SpokeUtils.js +8 -14
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/esm/utils/common.d.ts +0 -1
- package/dist/esm/utils/common.js +0 -1
- package/dist/esm/utils/common.js.map +1 -1
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +4 -5
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
- package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +1 -5
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
- package/dist/types/clients/SpokePoolClient.d.ts +0 -8
- package/dist/types/clients/SpokePoolClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockSpokePoolClient.d.ts +1 -2
- package/dist/types/clients/mocks/MockSpokePoolClient.d.ts.map +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/providers/index.d.ts +0 -1
- package/dist/types/providers/index.d.ts.map +1 -1
- package/dist/types/utils/AddressUtils.d.ts +0 -2
- package/dist/types/utils/AddressUtils.d.ts.map +1 -1
- package/dist/types/utils/DepositUtils.d.ts +1 -2
- package/dist/types/utils/DepositUtils.d.ts.map +1 -1
- package/dist/types/utils/EventUtils.d.ts.map +1 -1
- package/dist/types/utils/NetworkUtils.d.ts +0 -6
- package/dist/types/utils/NetworkUtils.d.ts.map +1 -1
- package/dist/types/utils/SpokeUtils.d.ts +0 -1
- package/dist/types/utils/SpokeUtils.d.ts.map +1 -1
- package/dist/types/utils/common.d.ts +0 -1
- package/dist/types/utils/common.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/clients/BundleDataClient/BundleDataClient.ts +224 -418
- package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +8 -0
- package/src/clients/BundleDataClient/utils/FillUtils.ts +2 -66
- package/src/clients/SpokePoolClient.ts +3 -16
- package/src/clients/mocks/MockSpokePoolClient.ts +1 -14
- package/src/constants.ts +3 -3
- package/src/providers/index.ts +0 -1
- package/src/utils/AddressUtils.ts +0 -26
- package/src/utils/DepositUtils.ts +2 -11
- package/src/utils/EventUtils.ts +1 -29
- package/src/utils/NetworkUtils.ts +0 -11
- package/src/utils/SpokeUtils.ts +9 -22
- package/src/utils/common.ts +0 -2
- package/dist/cjs/providers/mockProvider.d.ts +0 -19
- package/dist/cjs/providers/mockProvider.js +0 -70
- package/dist/cjs/providers/mockProvider.js.map +0 -1
- package/dist/esm/providers/mockProvider.d.ts +0 -23
- package/dist/esm/providers/mockProvider.js +0 -73
- package/dist/esm/providers/mockProvider.js.map +0 -1
- package/dist/types/providers/mockProvider.d.ts +0 -24
- package/dist/types/providers/mockProvider.d.ts.map +0 -1
- package/src/providers/mockProvider.ts +0 -77
|
@@ -33,13 +33,10 @@ import {
|
|
|
33
33
|
getImpliedBundleBlockRanges,
|
|
34
34
|
isSlowFill,
|
|
35
35
|
mapAsync,
|
|
36
|
-
filterAsync,
|
|
37
36
|
bnUint32Max,
|
|
38
37
|
isZeroValueDeposit,
|
|
39
38
|
findFillEvent,
|
|
40
39
|
isZeroValueFillOrSlowFillRequest,
|
|
41
|
-
chainIsEvm,
|
|
42
|
-
isValidEvmAddress,
|
|
43
40
|
} from "../../utils";
|
|
44
41
|
import winston from "winston";
|
|
45
42
|
import {
|
|
@@ -50,14 +47,11 @@ import {
|
|
|
50
47
|
getRefundsFromBundle,
|
|
51
48
|
getWidestPossibleExpectedBlockRange,
|
|
52
49
|
isChainDisabled,
|
|
53
|
-
isEvmRepaymentValid,
|
|
54
50
|
PoolRebalanceRoot,
|
|
55
51
|
prettyPrintV3SpokePoolEvents,
|
|
56
52
|
V3DepositWithBlock,
|
|
57
53
|
V3FillWithBlock,
|
|
58
|
-
verifyFillRepayment,
|
|
59
54
|
} from "./utils";
|
|
60
|
-
import { PRE_FILL_MIN_CONFIG_STORE_VERSION } from "../../constants";
|
|
61
55
|
|
|
62
56
|
// max(uint256) - 1
|
|
63
57
|
export const INFINITE_FILL_DEADLINE = bnUint32Max;
|
|
@@ -66,10 +60,6 @@ type DataCache = Record<string, Promise<LoadDataReturnValue>>;
|
|
|
66
60
|
|
|
67
61
|
// V3 dictionary helper functions
|
|
68
62
|
function updateExpiredDepositsV3(dict: ExpiredDepositsToRefundV3, deposit: V3DepositWithBlock): void {
|
|
69
|
-
assert(
|
|
70
|
-
chainIsEvm(deposit.originChainId) && isValidEvmAddress(deposit.depositor),
|
|
71
|
-
"expired depositor cannot be refunded"
|
|
72
|
-
);
|
|
73
63
|
const { originChainId, inputToken } = deposit;
|
|
74
64
|
if (!dict?.[originChainId]?.[inputToken]) {
|
|
75
65
|
assign(dict, [originChainId, inputToken], []);
|
|
@@ -90,14 +80,8 @@ function updateBundleFillsV3(
|
|
|
90
80
|
fill: V3FillWithBlock,
|
|
91
81
|
lpFeePct: BigNumber,
|
|
92
82
|
repaymentChainId: number,
|
|
93
|
-
repaymentToken: string
|
|
94
|
-
repaymentAddress: string
|
|
83
|
+
repaymentToken: string
|
|
95
84
|
): void {
|
|
96
|
-
// We shouldn't pass any unrepayable fills into this function, so we perform an extra safety check.
|
|
97
|
-
assert(
|
|
98
|
-
chainIsEvm(repaymentChainId) && isEvmRepaymentValid(fill, repaymentChainId),
|
|
99
|
-
"validatedBundleV3Fills dictionary should only contain fills with valid repayment information"
|
|
100
|
-
);
|
|
101
85
|
if (!dict?.[repaymentChainId]?.[repaymentToken]) {
|
|
102
86
|
assign(dict, [repaymentChainId, repaymentToken], {
|
|
103
87
|
fills: [],
|
|
@@ -107,19 +91,19 @@ function updateBundleFillsV3(
|
|
|
107
91
|
});
|
|
108
92
|
}
|
|
109
93
|
|
|
110
|
-
const bundleFill: BundleFillV3 = { ...fill, lpFeePct
|
|
94
|
+
const bundleFill: BundleFillV3 = { ...fill, lpFeePct };
|
|
111
95
|
|
|
112
96
|
// Add all fills, slow and fast, to dictionary.
|
|
113
97
|
assign(dict, [repaymentChainId, repaymentToken, "fills"], [bundleFill]);
|
|
114
98
|
|
|
115
99
|
// All fills update the bundle LP fees.
|
|
116
100
|
const refundObj = dict[repaymentChainId][repaymentToken];
|
|
117
|
-
const realizedLpFee =
|
|
101
|
+
const realizedLpFee = fill.inputAmount.mul(bundleFill.lpFeePct).div(fixedPointAdjustment);
|
|
118
102
|
refundObj.realizedLpFees = refundObj.realizedLpFees ? refundObj.realizedLpFees.add(realizedLpFee) : realizedLpFee;
|
|
119
103
|
|
|
120
104
|
// Only fast fills get refunded.
|
|
121
|
-
if (!isSlowFill(
|
|
122
|
-
const refundAmount =
|
|
105
|
+
if (!isSlowFill(fill)) {
|
|
106
|
+
const refundAmount = fill.inputAmount.mul(fixedPointAdjustment.sub(lpFeePct)).div(fixedPointAdjustment);
|
|
123
107
|
refundObj.totalRefundAmount = refundObj.totalRefundAmount
|
|
124
108
|
? refundObj.totalRefundAmount.add(refundAmount)
|
|
125
109
|
: refundAmount;
|
|
@@ -127,10 +111,10 @@ function updateBundleFillsV3(
|
|
|
127
111
|
// Instantiate dictionary if it doesn't exist.
|
|
128
112
|
refundObj.refunds ??= {};
|
|
129
113
|
|
|
130
|
-
if (refundObj.refunds[
|
|
131
|
-
refundObj.refunds[
|
|
114
|
+
if (refundObj.refunds[fill.relayer]) {
|
|
115
|
+
refundObj.refunds[fill.relayer] = refundObj.refunds[fill.relayer].add(refundAmount);
|
|
132
116
|
} else {
|
|
133
|
-
refundObj.refunds[
|
|
117
|
+
refundObj.refunds[fill.relayer] = refundAmount;
|
|
134
118
|
}
|
|
135
119
|
}
|
|
136
120
|
}
|
|
@@ -147,10 +131,6 @@ function updateBundleExcessSlowFills(
|
|
|
147
131
|
}
|
|
148
132
|
|
|
149
133
|
function updateBundleSlowFills(dict: BundleSlowFills, deposit: V3DepositWithBlock & { lpFeePct: BigNumber }): void {
|
|
150
|
-
assert(
|
|
151
|
-
chainIsEvm(deposit.destinationChainId) && isValidEvmAddress(deposit.recipient),
|
|
152
|
-
"slow fill recipient cannot be paid"
|
|
153
|
-
);
|
|
154
134
|
const { destinationChainId, outputToken } = deposit;
|
|
155
135
|
if (!dict?.[destinationChainId]?.[outputToken]) {
|
|
156
136
|
assign(dict, [destinationChainId, outputToken], []);
|
|
@@ -254,6 +234,7 @@ export class BundleDataClient {
|
|
|
254
234
|
bundleData: prettyPrintV3SpokePoolEvents(
|
|
255
235
|
bundleData.bundleDepositsV3,
|
|
256
236
|
bundleData.bundleFillsV3,
|
|
237
|
+
[], // Invalid fills are not persisted to Arweave.
|
|
257
238
|
bundleData.bundleSlowFillsV3,
|
|
258
239
|
bundleData.expiredDepositsToRefundV3,
|
|
259
240
|
bundleData.unexecutableSlowFills
|
|
@@ -301,7 +282,7 @@ export class BundleDataClient {
|
|
|
301
282
|
// so as not to affect this approximate refund count.
|
|
302
283
|
const arweaveData = await this.loadArweaveData(bundleEvaluationBlockRanges);
|
|
303
284
|
if (arweaveData === undefined) {
|
|
304
|
-
combinedRefunds =
|
|
285
|
+
combinedRefunds = this.getApproximateRefundsForBlockRange(chainIds, bundleEvaluationBlockRanges);
|
|
305
286
|
} else {
|
|
306
287
|
const { bundleFillsV3, expiredDepositsToRefundV3 } = arweaveData;
|
|
307
288
|
combinedRefunds = getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3);
|
|
@@ -322,72 +303,50 @@ export class BundleDataClient {
|
|
|
322
303
|
}
|
|
323
304
|
|
|
324
305
|
// @dev This helper function should probably be moved to the InventoryClient
|
|
325
|
-
|
|
306
|
+
getApproximateRefundsForBlockRange(chainIds: number[], blockRanges: number[][]): CombinedRefunds {
|
|
326
307
|
const refundsForChain: CombinedRefunds = {};
|
|
327
308
|
for (const chainId of chainIds) {
|
|
328
309
|
if (this.spokePoolClients[chainId] === undefined) {
|
|
329
310
|
continue;
|
|
330
311
|
}
|
|
331
312
|
const chainIndex = chainIds.indexOf(chainId);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (
|
|
339
|
-
fill.blockNumber < blockRanges[chainIndex][0] ||
|
|
340
|
-
fill.blockNumber > blockRanges[chainIndex][1] ||
|
|
341
|
-
isZeroValueFillOrSlowFillRequest(fill)
|
|
342
|
-
) {
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
313
|
+
this.spokePoolClients[chainId]
|
|
314
|
+
.getFills()
|
|
315
|
+
.filter((fill) => {
|
|
316
|
+
if (fill.blockNumber < blockRanges[chainIndex][0] || fill.blockNumber > blockRanges[chainIndex][1]) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
345
319
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
351
|
-
const hasMatchingDeposit =
|
|
352
|
-
matchingDeposit !== undefined &&
|
|
353
|
-
this.getRelayHashFromEvent(fill) === this.getRelayHashFromEvent(matchingDeposit);
|
|
354
|
-
if (hasMatchingDeposit) {
|
|
355
|
-
const validRepayment = await verifyFillRepayment(
|
|
356
|
-
fill,
|
|
357
|
-
this.spokePoolClients[fill.destinationChainId].spokePool.provider,
|
|
358
|
-
matchingDeposit,
|
|
359
|
-
// @dev: to get valid repayment chain ID's, get all chain IDs for the bundle block range and remove
|
|
360
|
-
// disabled block ranges.
|
|
361
|
-
this.clients.configStoreClient
|
|
362
|
-
.getChainIdIndicesForBlock(blockRanges[0][1])
|
|
363
|
-
.filter((_chainId, i) => !isChainDisabled(blockRanges[i]))
|
|
364
|
-
);
|
|
365
|
-
if (!isDefined(validRepayment)) {
|
|
320
|
+
// If origin spoke pool client isn't defined, we can't validate it.
|
|
321
|
+
if (this.spokePoolClients[fill.originChainId] === undefined) {
|
|
366
322
|
return false;
|
|
367
323
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
fill
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
324
|
+
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
325
|
+
const hasMatchingDeposit =
|
|
326
|
+
matchingDeposit !== undefined &&
|
|
327
|
+
this.getRelayHashFromEvent(fill) === this.getRelayHashFromEvent(matchingDeposit);
|
|
328
|
+
return hasMatchingDeposit;
|
|
329
|
+
})
|
|
330
|
+
.forEach((fill) => {
|
|
331
|
+
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
332
|
+
assert(isDefined(matchingDeposit), "Deposit not found for fill.");
|
|
333
|
+
const { chainToSendRefundTo, repaymentToken } = getRefundInformationFromFill(
|
|
334
|
+
fill,
|
|
335
|
+
this.clients.hubPoolClient,
|
|
336
|
+
blockRanges,
|
|
337
|
+
this.chainIdListForBundleEvaluationBlockNumbers,
|
|
338
|
+
matchingDeposit!.fromLiteChain // Use ! because we've already asserted that matchingDeposit is defined.
|
|
339
|
+
);
|
|
340
|
+
// Assume that lp fees are 0 for the sake of speed. In the future we could batch compute
|
|
341
|
+
// these or make hardcoded assumptions based on the origin-repayment chain direction. This might result
|
|
342
|
+
// in slight over estimations of refunds, but its not clear whether underestimating or overestimating is
|
|
343
|
+
// worst from the relayer's perspective.
|
|
344
|
+
const { relayer, inputAmount: refundAmount } = fill;
|
|
345
|
+
refundsForChain[chainToSendRefundTo] ??= {};
|
|
346
|
+
refundsForChain[chainToSendRefundTo][repaymentToken] ??= {};
|
|
347
|
+
const existingRefundAmount = refundsForChain[chainToSendRefundTo][repaymentToken][relayer] ?? bnZero;
|
|
348
|
+
refundsForChain[chainToSendRefundTo][repaymentToken][relayer] = existingRefundAmount.add(refundAmount);
|
|
349
|
+
});
|
|
391
350
|
}
|
|
392
351
|
return refundsForChain;
|
|
393
352
|
}
|
|
@@ -431,7 +390,7 @@ export class BundleDataClient {
|
|
|
431
390
|
async getLatestPoolRebalanceRoot(): Promise<{ root: PoolRebalanceRoot; blockRanges: number[][] }> {
|
|
432
391
|
const { bundleData, blockRanges } = await this.getLatestProposedBundleData();
|
|
433
392
|
const hubPoolClient = this.clients.hubPoolClient;
|
|
434
|
-
const root = _buildPoolRebalanceRoot(
|
|
393
|
+
const root = await _buildPoolRebalanceRoot(
|
|
435
394
|
hubPoolClient.latestBlockSearched,
|
|
436
395
|
blockRanges[0][1],
|
|
437
396
|
bundleData.bundleDepositsV3,
|
|
@@ -514,7 +473,7 @@ export class BundleDataClient {
|
|
|
514
473
|
// ok for this use case.
|
|
515
474
|
const arweaveData = await this.loadArweaveData(pendingBundleBlockRanges);
|
|
516
475
|
if (arweaveData === undefined) {
|
|
517
|
-
combinedRefunds.push(
|
|
476
|
+
combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, pendingBundleBlockRanges));
|
|
518
477
|
} else {
|
|
519
478
|
const { bundleFillsV3, expiredDepositsToRefundV3 } = arweaveData;
|
|
520
479
|
combinedRefunds.push(getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3));
|
|
@@ -529,7 +488,7 @@ export class BundleDataClient {
|
|
|
529
488
|
// - Only look up fills sent after the pending bundle's end blocks
|
|
530
489
|
// - Skip LP fee computations and just assume the relayer is being refunded the full deposit.inputAmount
|
|
531
490
|
const start = performance.now();
|
|
532
|
-
combinedRefunds.push(
|
|
491
|
+
combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, widestBundleBlockRanges));
|
|
533
492
|
this.logger.debug({
|
|
534
493
|
at: "BundleDataClient#getNextBundleRefunds",
|
|
535
494
|
message: `Loading approximate refunds for next bundle in ${Math.round(performance.now() - start) / 1000}s.`,
|
|
@@ -696,7 +655,6 @@ export class BundleDataClient {
|
|
|
696
655
|
const bundleDepositsV3: BundleDepositsV3 = {}; // Deposits in bundle block range.
|
|
697
656
|
const bundleFillsV3: BundleFillsV3 = {}; // Fills to refund in bundle block range.
|
|
698
657
|
const bundleInvalidFillsV3: V3FillWithBlock[] = []; // Fills that are not valid in this bundle.
|
|
699
|
-
const bundleUnrepayableFillsV3: V3FillWithBlock[] = []; // Fills that are not repayable in this bundle.
|
|
700
658
|
const bundleSlowFillsV3: BundleSlowFills = {}; // Deposits that we need to send slow fills
|
|
701
659
|
// for in this bundle.
|
|
702
660
|
const expiredDepositsToRefundV3: ExpiredDepositsToRefundV3 = {};
|
|
@@ -783,7 +741,7 @@ export class BundleDataClient {
|
|
|
783
741
|
// Note: Since there are no partial fills in v3, there should only be one fill per relay hash.
|
|
784
742
|
// Moreover, the SpokePool blocks multiple slow fill requests, so
|
|
785
743
|
// there should also only be one slow fill request per relay hash.
|
|
786
|
-
|
|
744
|
+
deposit?: V3DepositWithBlock;
|
|
787
745
|
fill?: V3FillWithBlock;
|
|
788
746
|
slowFillRequest?: SlowFillRequestWithBlock;
|
|
789
747
|
};
|
|
@@ -794,29 +752,7 @@ export class BundleDataClient {
|
|
|
794
752
|
const bundleDepositHashes: string[] = [];
|
|
795
753
|
const olderDepositHashes: string[] = [];
|
|
796
754
|
|
|
797
|
-
|
|
798
|
-
const [relayDataHash, i] = depositHash.split("@");
|
|
799
|
-
return { relayDataHash, index: Number(i) };
|
|
800
|
-
};
|
|
801
|
-
|
|
802
|
-
// We use the following toggle to aid with the migration to pre-fills. The first bundle proposed using this
|
|
803
|
-
// pre-fill logic can double refund pre-fills that have already been filled in the last bundle, because the
|
|
804
|
-
// last bundle did not recognize a fill as a pre-fill. Therefore the developer should ensure that the version
|
|
805
|
-
// is bumped to the PRE_FILL_MIN_CONFIG_STORE_VERSION version before the first pre-fill bundle is proposed.
|
|
806
|
-
// To test the following bundle after this, the developer can set the FORCE_REFUND_PREFILLS environment variable
|
|
807
|
-
// to "true" simulate the bundle with pre-fill refunds.
|
|
808
|
-
// @todo Remove this logic once we have advanced sufficiently past the pre-fill migration.
|
|
809
|
-
const startBlockForMainnet = getBlockRangeForChain(
|
|
810
|
-
blockRangesForChains,
|
|
811
|
-
this.clients.hubPoolClient.chainId,
|
|
812
|
-
this.chainIdListForBundleEvaluationBlockNumbers
|
|
813
|
-
)[0];
|
|
814
|
-
const versionAtProposalBlock = this.clients.configStoreClient.getConfigStoreVersionForBlock(startBlockForMainnet);
|
|
815
|
-
const canRefundPrefills =
|
|
816
|
-
versionAtProposalBlock >= PRE_FILL_MIN_CONFIG_STORE_VERSION || process.env.FORCE_REFUND_PREFILLS === "true";
|
|
817
|
-
|
|
818
|
-
// Prerequisite step: Load all deposit events from the current or older bundles into the v3RelayHashes dictionary
|
|
819
|
-
// for convenient matching with fills.
|
|
755
|
+
let depositCounter = 0;
|
|
820
756
|
for (const originChainId of allChainIds) {
|
|
821
757
|
const originClient = spokePoolClients[originChainId];
|
|
822
758
|
const originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
@@ -826,59 +762,50 @@ export class BundleDataClient {
|
|
|
826
762
|
continue;
|
|
827
763
|
}
|
|
828
764
|
originClient.getDepositsForDestinationChainWithDuplicates(destinationChainId).forEach((deposit) => {
|
|
765
|
+
// Only evaluate deposits that are in this bundle or in previous bundles. This means we cannot issue fill
|
|
766
|
+
// refunds or slow fills here for deposits that are in future bundles (i.e. "pre-fills"). Instead, we'll
|
|
767
|
+
// evaluate these pre-fills once the deposit is inside the "current" bundle block range.
|
|
829
768
|
if (deposit.blockNumber > originChainBlockRange[1] || isZeroValueDeposit(deposit)) {
|
|
830
769
|
return;
|
|
831
770
|
}
|
|
771
|
+
depositCounter++;
|
|
832
772
|
const relayDataHash = this.getRelayHashFromEvent(deposit);
|
|
833
773
|
|
|
774
|
+
// Duplicate deposits are treated like normal deposits.
|
|
834
775
|
if (!v3RelayHashes[relayDataHash]) {
|
|
835
776
|
v3RelayHashes[relayDataHash] = {
|
|
836
|
-
|
|
777
|
+
deposit: deposit,
|
|
837
778
|
fill: undefined,
|
|
838
779
|
slowFillRequest: undefined,
|
|
839
780
|
};
|
|
840
|
-
} else {
|
|
841
|
-
v3RelayHashes[relayDataHash].deposits!.push(deposit);
|
|
842
781
|
}
|
|
843
782
|
|
|
844
|
-
//
|
|
845
|
-
//
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
783
|
+
// Once we've saved the deposit hash into v3RelayHashes, then we can exit early here if the inputAmount
|
|
784
|
+
// is 0 because there can be no expired amount to refund and no unexecutable slow fill amount to return
|
|
785
|
+
// if this deposit did expire. Input amount can only be zero at this point if the message is non-empty,
|
|
786
|
+
// but the message doesn't matter for expired deposits and unexecutable slow fills.
|
|
787
|
+
if (deposit.inputAmount.eq(0)) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Evaluate all expired deposits after fetching fill statuses,
|
|
792
|
+
// since we can't know for certain whether an expired deposit was filled a long time ago.
|
|
853
793
|
if (deposit.blockNumber >= originChainBlockRange[0]) {
|
|
854
|
-
bundleDepositHashes.push(
|
|
794
|
+
bundleDepositHashes.push(relayDataHash);
|
|
855
795
|
updateBundleDepositsV3(bundleDepositsV3, deposit);
|
|
856
796
|
} else if (deposit.blockNumber < originChainBlockRange[0]) {
|
|
857
|
-
olderDepositHashes.push(
|
|
797
|
+
olderDepositHashes.push(relayDataHash);
|
|
858
798
|
}
|
|
859
799
|
});
|
|
860
800
|
}
|
|
861
801
|
}
|
|
862
802
|
this.logger.debug({
|
|
863
803
|
at: "BundleDataClient#loadData",
|
|
864
|
-
message: `Processed ${
|
|
865
|
-
performance.now() - start
|
|
866
|
-
}ms.`,
|
|
804
|
+
message: `Processed ${depositCounter} deposits in ${performance.now() - start}ms.`,
|
|
867
805
|
});
|
|
868
806
|
start = performance.now();
|
|
869
807
|
|
|
870
|
-
// Process fills
|
|
871
|
-
// - Every single fill whose type is not SlowFill in the bundle block range whose relay data matches
|
|
872
|
-
// with a deposit in the same or an older range produces a refund to the filler,
|
|
873
|
-
// unless the specified filler address cannot be repaid on the repayment chain.
|
|
874
|
-
// - Fills can match with duplicate deposits, so for every matched fill whose type is not SlowFill
|
|
875
|
-
// in the bundle block range, produce a refund to the filler for each matched deposit.
|
|
876
|
-
// - For every SlowFill in the block range that matches with multiple deposits, produce a refund to the depositor
|
|
877
|
-
// for every deposit except except the first.
|
|
878
|
-
|
|
879
|
-
// Assumptions about fills:
|
|
880
|
-
// - Duplicate fills for the same relay data hash are impossible to send.
|
|
881
|
-
// - Fills can only be sent before the deposit's fillDeadline.
|
|
808
|
+
// Process fills now that we've populated relay hash dictionary with deposits:
|
|
882
809
|
const validatedBundleV3Fills: (V3FillWithBlock & { quoteTimestamp: number })[] = [];
|
|
883
810
|
const validatedBundleSlowFills: V3DepositWithBlock[] = [];
|
|
884
811
|
const validatedBundleUnexecutableSlowFills: V3DepositWithBlock[] = [];
|
|
@@ -892,8 +819,9 @@ export class BundleDataClient {
|
|
|
892
819
|
|
|
893
820
|
const destinationClient = spokePoolClients[destinationChainId];
|
|
894
821
|
const destinationChainBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
895
|
-
const originChainBlockRange = getBlockRangeForChain(blockRangesForChains, originChainId, chainIds);
|
|
896
822
|
|
|
823
|
+
// Keep track of fast fills that replaced slow fills, which we'll use to create "unexecutable" slow fills
|
|
824
|
+
// if the slow fill request was sent in a prior bundle.
|
|
897
825
|
const fastFillsReplacingSlowFills: string[] = [];
|
|
898
826
|
await forEachAsync(
|
|
899
827
|
destinationClient
|
|
@@ -905,79 +833,47 @@ export class BundleDataClient {
|
|
|
905
833
|
(fill) => fill.blockNumber <= destinationChainBlockRange[1] && !isZeroValueFillOrSlowFillRequest(fill)
|
|
906
834
|
),
|
|
907
835
|
async (fill) => {
|
|
908
|
-
fillCounter++;
|
|
909
836
|
const relayDataHash = this.getRelayHashFromEvent(fill);
|
|
837
|
+
fillCounter++;
|
|
838
|
+
|
|
910
839
|
if (v3RelayHashes[relayDataHash]) {
|
|
911
840
|
if (!v3RelayHashes[relayDataHash].fill) {
|
|
912
841
|
assert(
|
|
913
|
-
isDefined(v3RelayHashes[relayDataHash].
|
|
842
|
+
isDefined(v3RelayHashes[relayDataHash].deposit),
|
|
914
843
|
"Deposit should exist in relay hash dictionary."
|
|
915
844
|
);
|
|
845
|
+
// At this point, the v3RelayHashes entry already existed meaning that there is a matching deposit,
|
|
846
|
+
// so this fill is validated.
|
|
916
847
|
v3RelayHashes[relayDataHash].fill = fill;
|
|
917
848
|
if (fill.blockNumber >= destinationChainBlockRange[0]) {
|
|
918
|
-
|
|
919
|
-
fill,
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
allChainIds
|
|
923
|
-
);
|
|
924
|
-
if (!isDefined(fillToRefund)) {
|
|
925
|
-
bundleUnrepayableFillsV3.push(fill);
|
|
926
|
-
// We don't return here yet because we still need to mark unexecutable slow fill leaves
|
|
927
|
-
// or duplicate deposits. However, we won't issue a fast fill refund.
|
|
928
|
-
} else {
|
|
929
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
930
|
-
validatedBundleV3Fills.push({
|
|
931
|
-
...fillToRefund,
|
|
932
|
-
quoteTimestamp: v3RelayHashes[relayDataHash].deposits![0].quoteTimestamp,
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
// Now that we know this deposit has been filled on-chain, identify any duplicate deposits
|
|
936
|
-
// sent for this fill and refund them to the filler, because this value would not be paid out
|
|
937
|
-
// otherwise. These deposits can no longer expire and get refunded as an expired deposit,
|
|
938
|
-
// and they won't trigger a pre-fill refund because the fill is in this bundle.
|
|
939
|
-
// Pre-fill refunds only happen when deposits are sent in this bundle and the
|
|
940
|
-
// fill is from a prior bundle. Paying out the filler keeps the behavior consistent for how
|
|
941
|
-
// we deal with duplicate deposits regardless if the deposit is matched with a pre-fill or
|
|
942
|
-
// a current bundle fill.
|
|
943
|
-
const duplicateDeposits = v3RelayHashes[relayDataHash].deposits!.slice(1);
|
|
944
|
-
duplicateDeposits.forEach((duplicateDeposit) => {
|
|
945
|
-
if (isSlowFill(fill)) {
|
|
946
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, duplicateDeposit);
|
|
947
|
-
} else {
|
|
948
|
-
validatedBundleV3Fills.push({
|
|
949
|
-
...fillToRefund,
|
|
950
|
-
quoteTimestamp: duplicateDeposit.quoteTimestamp,
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
|
|
849
|
+
validatedBundleV3Fills.push({
|
|
850
|
+
...fill,
|
|
851
|
+
quoteTimestamp: v3RelayHashes[relayDataHash].deposit!.quoteTimestamp, // ! due to assert above
|
|
852
|
+
});
|
|
956
853
|
// If fill replaced a slow fill request, then mark it as one that might have created an
|
|
957
854
|
// unexecutable slow fill. We can't know for sure until we check the slow fill request
|
|
958
855
|
// events.
|
|
856
|
+
// slow fill requests for deposits from or to lite chains are considered invalid
|
|
959
857
|
if (
|
|
960
858
|
fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
961
|
-
_canCreateSlowFillLeaf(v3RelayHashes[relayDataHash].
|
|
859
|
+
_canCreateSlowFillLeaf(v3RelayHashes[relayDataHash].deposit!)
|
|
962
860
|
) {
|
|
963
861
|
fastFillsReplacingSlowFills.push(relayDataHash);
|
|
964
862
|
}
|
|
965
863
|
}
|
|
966
|
-
} else {
|
|
967
|
-
throw new Error("Duplicate fill detected");
|
|
968
864
|
}
|
|
969
865
|
return;
|
|
970
866
|
}
|
|
971
867
|
|
|
972
868
|
// At this point, there is no relay hash dictionary entry for this fill, so we need to
|
|
973
|
-
// instantiate the entry.
|
|
869
|
+
// instantiate the entry.
|
|
974
870
|
v3RelayHashes[relayDataHash] = {
|
|
975
|
-
|
|
976
|
-
fill,
|
|
871
|
+
deposit: undefined,
|
|
872
|
+
fill: fill,
|
|
977
873
|
slowFillRequest: undefined,
|
|
978
874
|
};
|
|
979
875
|
|
|
980
|
-
// TODO: We
|
|
876
|
+
// TODO: We might be able to remove the following historical query once we deprecate the deposit()
|
|
981
877
|
// function since there won't be any old, unexpired deposits anymore assuming the spoke pool client
|
|
982
878
|
// lookbacks have been validated, which they should be before we run this function.
|
|
983
879
|
|
|
@@ -1001,40 +897,17 @@ export class BundleDataClient {
|
|
|
1001
897
|
bundleInvalidFillsV3.push(fill);
|
|
1002
898
|
} else {
|
|
1003
899
|
const matchedDeposit = historicalDeposit.deposit;
|
|
1004
|
-
//
|
|
1005
|
-
//
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
matchedDeposit,
|
|
1016
|
-
allChainIds
|
|
1017
|
-
);
|
|
1018
|
-
if (!isDefined(fillToRefund)) {
|
|
1019
|
-
bundleUnrepayableFillsV3.push(fill);
|
|
1020
|
-
// Don't return yet as we still need to mark down any unexecutable slow fill leaves
|
|
1021
|
-
// in case this fast fill replaced a slow fill request.
|
|
1022
|
-
} else {
|
|
1023
|
-
// @dev Since queryHistoricalDepositForFill validates the fill by checking individual
|
|
1024
|
-
// object property values against the deposit's, we
|
|
1025
|
-
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
1026
|
-
// historical deposit query is not working as expected.
|
|
1027
|
-
assert(this.getRelayHashFromEvent(matchedDeposit) === relayDataHash, "Relay hashes should match.");
|
|
1028
|
-
validatedBundleV3Fills.push({
|
|
1029
|
-
...fillToRefund,
|
|
1030
|
-
quoteTimestamp: matchedDeposit.quoteTimestamp,
|
|
1031
|
-
});
|
|
1032
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
1033
|
-
|
|
1034
|
-
// No need to check for duplicate deposits here since duplicate deposits with
|
|
1035
|
-
// infinite deadlines are impossible to send via unsafeDeposit().
|
|
1036
|
-
}
|
|
1037
|
-
|
|
900
|
+
// @dev Since queryHistoricalDepositForFill validates the fill by checking individual
|
|
901
|
+
// object property values against the deposit's, we
|
|
902
|
+
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
903
|
+
// historical deposit query is not working as expected.
|
|
904
|
+
assert(this.getRelayHashFromEvent(matchedDeposit) === relayDataHash, "Relay hashes should match.");
|
|
905
|
+
validatedBundleV3Fills.push({
|
|
906
|
+
...fill,
|
|
907
|
+
quoteTimestamp: matchedDeposit.quoteTimestamp,
|
|
908
|
+
});
|
|
909
|
+
v3RelayHashes[relayDataHash].deposit = matchedDeposit;
|
|
910
|
+
// slow fill requests for deposits from or to lite chains are considered invalid
|
|
1038
911
|
if (
|
|
1039
912
|
fill.relayExecutionInfo.fillType === FillType.ReplacedSlowFill &&
|
|
1040
913
|
_canCreateSlowFillLeaf(matchedDeposit)
|
|
@@ -1046,14 +919,8 @@ export class BundleDataClient {
|
|
|
1046
919
|
}
|
|
1047
920
|
);
|
|
1048
921
|
|
|
1049
|
-
// Process slow fill requests
|
|
1050
|
-
//
|
|
1051
|
-
// - Slow fill leaves cannot be produced for deposits that have been filled.
|
|
1052
|
-
|
|
1053
|
-
// Assumptions about fills:
|
|
1054
|
-
// - Duplicate slow fill requests for the same relay data hash are impossible to send.
|
|
1055
|
-
// - Slow fill requests can only be sent before the deposit's fillDeadline.
|
|
1056
|
-
// - Slow fill requests for a deposit that has been filled.
|
|
922
|
+
// Process slow fill requests. One invariant we need to maintain is that we cannot create slow fill requests
|
|
923
|
+
// for deposits that would expire in this bundle.
|
|
1057
924
|
await forEachAsync(
|
|
1058
925
|
destinationClient
|
|
1059
926
|
.getSlowFillRequestsForOriginChain(originChainId)
|
|
@@ -1066,40 +933,46 @@ export class BundleDataClient {
|
|
|
1066
933
|
|
|
1067
934
|
if (v3RelayHashes[relayDataHash]) {
|
|
1068
935
|
if (!v3RelayHashes[relayDataHash].slowFillRequest) {
|
|
936
|
+
// At this point, the v3RelayHashes entry already existed meaning that there is either a matching
|
|
937
|
+
// fill or deposit.
|
|
1069
938
|
v3RelayHashes[relayDataHash].slowFillRequest = slowFillRequest;
|
|
1070
939
|
if (v3RelayHashes[relayDataHash].fill) {
|
|
1071
|
-
//
|
|
1072
|
-
//
|
|
1073
|
-
// for a fill older than this slow fill request.
|
|
940
|
+
// If there is a fill matching the relay hash, then this slow fill request can't be used
|
|
941
|
+
// to create a slow fill for a filled deposit.
|
|
1074
942
|
return;
|
|
1075
943
|
}
|
|
1076
944
|
assert(
|
|
1077
|
-
isDefined(v3RelayHashes[relayDataHash].
|
|
945
|
+
isDefined(v3RelayHashes[relayDataHash].deposit),
|
|
1078
946
|
"Deposit should exist in relay hash dictionary."
|
|
1079
947
|
);
|
|
1080
|
-
|
|
948
|
+
// The ! is safe here because we've already checked that the deposit exists in the relay hash dictionary.
|
|
949
|
+
const matchedDeposit = v3RelayHashes[relayDataHash].deposit!;
|
|
1081
950
|
|
|
951
|
+
// If there is no fill matching the relay hash, then this might be a valid slow fill request
|
|
952
|
+
// that we should produce a slow fill leaf for. Check if the slow fill request is in the
|
|
953
|
+
// destination chain block range.
|
|
1082
954
|
if (
|
|
1083
955
|
slowFillRequest.blockNumber >= destinationChainBlockRange[0] &&
|
|
1084
956
|
_canCreateSlowFillLeaf(matchedDeposit) &&
|
|
957
|
+
// Deposit must not have expired in this bundle.
|
|
1085
958
|
!_depositIsExpired(matchedDeposit)
|
|
1086
959
|
) {
|
|
960
|
+
// At this point, the v3RelayHashes entry already existed meaning that there is a matching deposit,
|
|
961
|
+
// so this slow fill request relay data is correct.
|
|
1087
962
|
validatedBundleSlowFills.push(matchedDeposit);
|
|
1088
963
|
}
|
|
1089
|
-
} else {
|
|
1090
|
-
throw new Error("Duplicate slow fill request detected.");
|
|
1091
964
|
}
|
|
1092
965
|
return;
|
|
1093
966
|
}
|
|
1094
967
|
|
|
1095
968
|
// Instantiate dictionary if there is neither a deposit nor fill matching it.
|
|
1096
969
|
v3RelayHashes[relayDataHash] = {
|
|
1097
|
-
|
|
970
|
+
deposit: undefined,
|
|
1098
971
|
fill: undefined,
|
|
1099
972
|
slowFillRequest: slowFillRequest,
|
|
1100
973
|
};
|
|
1101
974
|
|
|
1102
|
-
// TODO: We
|
|
975
|
+
// TODO: We might be able to remove the following historical query once we deprecate the deposit()
|
|
1103
976
|
// function since there won't be any old, unexpired deposits anymore assuming the spoke pool client
|
|
1104
977
|
// lookbacks have been validated, which they should be before we run this function.
|
|
1105
978
|
|
|
@@ -1112,19 +985,15 @@ export class BundleDataClient {
|
|
|
1112
985
|
// found using such a method) because infinite fill deadlines cannot be produced from the unsafeDepositV3()
|
|
1113
986
|
// function.
|
|
1114
987
|
if (
|
|
1115
|
-
|
|
1116
|
-
slowFillRequest.
|
|
988
|
+
slowFillRequest.blockNumber >= destinationChainBlockRange[0] &&
|
|
989
|
+
INFINITE_FILL_DEADLINE.eq(slowFillRequest.fillDeadline)
|
|
1117
990
|
) {
|
|
1118
991
|
const historicalDeposit = await queryHistoricalDepositForFill(originClient, slowFillRequest);
|
|
1119
992
|
if (!historicalDeposit.found) {
|
|
993
|
+
// TODO: Invalid slow fill request. Maybe worth logging.
|
|
1120
994
|
return;
|
|
1121
995
|
}
|
|
1122
996
|
const matchedDeposit: V3DepositWithBlock = historicalDeposit.deposit;
|
|
1123
|
-
// If deposit is in a following bundle, then this slow fill request will have to be created
|
|
1124
|
-
// once that deposit is in the current bundle.
|
|
1125
|
-
if (matchedDeposit.blockNumber > originChainBlockRange[1]) {
|
|
1126
|
-
return;
|
|
1127
|
-
}
|
|
1128
997
|
// @dev Since queryHistoricalDepositForFill validates the slow fill request by checking individual
|
|
1129
998
|
// object property values against the deposit's, we
|
|
1130
999
|
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
@@ -1133,9 +1002,13 @@ export class BundleDataClient {
|
|
|
1133
1002
|
this.getRelayHashFromEvent(matchedDeposit) === relayDataHash,
|
|
1134
1003
|
"Deposit relay hashes should match."
|
|
1135
1004
|
);
|
|
1136
|
-
v3RelayHashes[relayDataHash].
|
|
1005
|
+
v3RelayHashes[relayDataHash].deposit = matchedDeposit;
|
|
1137
1006
|
|
|
1138
|
-
if (
|
|
1007
|
+
if (
|
|
1008
|
+
!_canCreateSlowFillLeaf(matchedDeposit) ||
|
|
1009
|
+
// Deposit must not have expired in this bundle.
|
|
1010
|
+
_depositIsExpired(matchedDeposit)
|
|
1011
|
+
) {
|
|
1139
1012
|
return;
|
|
1140
1013
|
}
|
|
1141
1014
|
validatedBundleSlowFills.push(matchedDeposit);
|
|
@@ -1143,143 +1016,122 @@ export class BundleDataClient {
|
|
|
1143
1016
|
}
|
|
1144
1017
|
);
|
|
1145
1018
|
|
|
1146
|
-
//
|
|
1147
|
-
//
|
|
1148
|
-
//
|
|
1149
|
-
// -
|
|
1150
|
-
//
|
|
1151
|
-
// -
|
|
1152
|
-
//
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
// If fill is in the current bundle then we can assume there is already a refund for it, so only
|
|
1180
|
-
// include this pre fill if the fill is in an older bundle.
|
|
1181
|
-
if (fill) {
|
|
1182
|
-
if (canRefundPrefills && fill.blockNumber < destinationChainBlockRange[0]) {
|
|
1183
|
-
const fillToRefund = await verifyFillRepayment(
|
|
1184
|
-
fill,
|
|
1185
|
-
destinationClient.spokePool.provider,
|
|
1186
|
-
v3RelayHashes[relayDataHash].deposits![0],
|
|
1187
|
-
allChainIds
|
|
1188
|
-
);
|
|
1189
|
-
if (!isDefined(fillToRefund)) {
|
|
1190
|
-
bundleUnrepayableFillsV3.push(fill);
|
|
1191
|
-
} else if (!isSlowFill(fill)) {
|
|
1192
|
-
v3RelayHashes[relayDataHash].fill = fillToRefund;
|
|
1019
|
+
// Deposits can be submitted an arbitrary amount of time after matching fills and slow fill requests.
|
|
1020
|
+
// Therefore, let's go through each deposit in this bundle again and check a few things in order:
|
|
1021
|
+
// - Has the deposit been filled ? If so, then we need to issue a relayer refund for
|
|
1022
|
+
// this "pre-fill" if the fill took place in a previous bundle.
|
|
1023
|
+
// - Or, has the deposit expired in this bundle? If so, then we need to issue an expiry refund.
|
|
1024
|
+
// - And finally, has the deposit been slow filled? If so, then we need to issue a slow fill leaf
|
|
1025
|
+
// for this "pre-slow-fill-request" if this request took place in a previous bundle.
|
|
1026
|
+
await mapAsync(
|
|
1027
|
+
bundleDepositHashes.filter((depositHash) => {
|
|
1028
|
+
const { deposit } = v3RelayHashes[depositHash];
|
|
1029
|
+
return (
|
|
1030
|
+
deposit && deposit.originChainId === originChainId && deposit.destinationChainId === destinationChainId
|
|
1031
|
+
);
|
|
1032
|
+
}),
|
|
1033
|
+
async (depositHash) => {
|
|
1034
|
+
const { deposit, fill, slowFillRequest } = v3RelayHashes[depositHash];
|
|
1035
|
+
if (!deposit) throw new Error("Deposit should exist in relay hash dictionary.");
|
|
1036
|
+
|
|
1037
|
+
// We are willing to refund a pre-fill multiple times for each duplicate deposit.
|
|
1038
|
+
// This is because a duplicate deposit for a pre-fill cannot get
|
|
1039
|
+
// refunded to the depositor anymore because its fill status on-chain has changed to Filled. Therefore
|
|
1040
|
+
// any duplicate deposits result in a net loss of funds for the depositor and effectively pay out
|
|
1041
|
+
// the pre-filler.
|
|
1042
|
+
|
|
1043
|
+
// If fill exists in memory, then the only case in which we need to create a refund is if the
|
|
1044
|
+
// the fill occurred in a previous bundle. There are no expiry refunds for filled deposits.
|
|
1045
|
+
if (fill) {
|
|
1046
|
+
if (fill.blockNumber < destinationChainBlockRange[0] && !isSlowFill(fill)) {
|
|
1047
|
+
// If fill is in the current bundle then we can assume there is already a refund for it, so only
|
|
1048
|
+
// include this pre fill if the fill is in an older bundle. If fill is after this current bundle, then
|
|
1049
|
+
// we won't consider it, following the previous treatment of fills after the bundle block range.
|
|
1193
1050
|
validatedBundleV3Fills.push({
|
|
1194
|
-
...
|
|
1051
|
+
...fill,
|
|
1195
1052
|
quoteTimestamp: deposit.quoteTimestamp,
|
|
1196
1053
|
});
|
|
1197
|
-
} else {
|
|
1198
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
1199
1054
|
}
|
|
1055
|
+
return;
|
|
1200
1056
|
}
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
1057
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1058
|
+
// If a slow fill request exists in memory, then we know the deposit has not been filled because fills
|
|
1059
|
+
// must follow slow fill requests and we would have seen the fill already if it existed. Therefore,
|
|
1060
|
+
// we can conclude that either the deposit has expired and we need to create a deposit expiry refund, or
|
|
1061
|
+
// we need to create a slow fill leaf for the deposit. The latter should only happen if the slow fill request
|
|
1062
|
+
// took place in a prior bundle otherwise we would have already created a slow fill leaf for it.
|
|
1063
|
+
if (slowFillRequest) {
|
|
1064
|
+
if (_depositIsExpired(deposit)) {
|
|
1065
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
1066
|
+
} else if (
|
|
1067
|
+
slowFillRequest.blockNumber < destinationChainBlockRange[0] &&
|
|
1068
|
+
_canCreateSlowFillLeaf(deposit)
|
|
1069
|
+
) {
|
|
1070
|
+
validatedBundleSlowFills.push(deposit);
|
|
1071
|
+
}
|
|
1072
|
+
return;
|
|
1219
1073
|
}
|
|
1220
|
-
return;
|
|
1221
|
-
}
|
|
1222
1074
|
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
//
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
if (canRefundPrefills) {
|
|
1237
|
-
const verifiedFill = await verifyFillRepayment(
|
|
1238
|
-
prefill!,
|
|
1239
|
-
destinationClient.spokePool.provider,
|
|
1075
|
+
// So at this point in the code, there is no fill or slow fill request in memory for this deposit.
|
|
1076
|
+
// We need to check its fill status on-chain to figure out whether to issue a refund or a slow fill leaf.
|
|
1077
|
+
// We can assume at this point that all fills or slow fill requests, if found, were in previous bundles
|
|
1078
|
+
// because the spoke pool client lookback would have returned this entire bundle of events and stored
|
|
1079
|
+
// them into the relay hash dictionary.
|
|
1080
|
+
const fillStatus = await _getFillStatusForDeposit(deposit, destinationChainBlockRange[1]);
|
|
1081
|
+
|
|
1082
|
+
// If deposit was filled, then we need to issue a refund for it.
|
|
1083
|
+
if (fillStatus === FillStatus.Filled) {
|
|
1084
|
+
// We need to find the fill event to issue a refund to the right relayer and repayment chain,
|
|
1085
|
+
// or msg.sender if relayer address is invalid for the repayment chain.
|
|
1086
|
+
const prefill = (await findFillEvent(
|
|
1087
|
+
destinationClient.spokePool,
|
|
1240
1088
|
deposit,
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
} else if (!isSlowFill(verifiedFill)) {
|
|
1089
|
+
destinationClient.deploymentBlock,
|
|
1090
|
+
destinationClient.latestBlockSearched
|
|
1091
|
+
)) as unknown as FillWithBlock;
|
|
1092
|
+
if (!isSlowFill(prefill)) {
|
|
1246
1093
|
validatedBundleV3Fills.push({
|
|
1247
|
-
...
|
|
1094
|
+
...prefill,
|
|
1248
1095
|
quoteTimestamp: deposit.quoteTimestamp,
|
|
1249
1096
|
});
|
|
1250
|
-
} else {
|
|
1251
|
-
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
1252
1097
|
}
|
|
1253
1098
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1099
|
+
// If deposit is not filled and its newly expired, we can create a deposit refund for it.
|
|
1100
|
+
// We don't check that fillDeadline >= bundleBlockTimestamps[destinationChainId][0] because
|
|
1101
|
+
// that would eliminate any deposits in this bundle with a very low fillDeadline like equal to 0
|
|
1102
|
+
// for example. Those should be included in this bundle of refunded deposits.
|
|
1103
|
+
else if (_depositIsExpired(deposit)) {
|
|
1104
|
+
updateExpiredDepositsV3(expiredDepositsToRefundV3, deposit);
|
|
1105
|
+
}
|
|
1106
|
+
// If slow fill requested, then issue a slow fill leaf for the deposit.
|
|
1107
|
+
else if (fillStatus === FillStatus.RequestedSlowFill) {
|
|
1108
|
+
// Input and Output tokens must be equivalent on the deposit for this to be slow filled.
|
|
1109
|
+
// Slow fill requests for deposits from or to lite chains are considered invalid
|
|
1110
|
+
if (_canCreateSlowFillLeaf(deposit)) {
|
|
1111
|
+
// If deposit newly expired, then we can't create a slow fill leaf for it but we can
|
|
1112
|
+
// create a deposit refund for it.
|
|
1113
|
+
validatedBundleSlowFills.push(deposit);
|
|
1114
|
+
}
|
|
1263
1115
|
}
|
|
1264
1116
|
}
|
|
1265
|
-
|
|
1117
|
+
);
|
|
1266
1118
|
|
|
1267
1119
|
// For all fills that came after a slow fill request, we can now check if the slow fill request
|
|
1268
1120
|
// was a valid one and whether it was created in a previous bundle. If so, then it created a slow fill
|
|
1269
1121
|
// leaf that is now unexecutable.
|
|
1270
1122
|
fastFillsReplacingSlowFills.forEach((relayDataHash) => {
|
|
1271
|
-
const {
|
|
1123
|
+
const { deposit, slowFillRequest, fill } = v3RelayHashes[relayDataHash];
|
|
1272
1124
|
assert(
|
|
1273
1125
|
fill?.relayExecutionInfo.fillType === FillType.ReplacedSlowFill,
|
|
1274
1126
|
"Fill type should be ReplacedSlowFill."
|
|
1275
1127
|
);
|
|
1276
1128
|
// Needed for TSC - are implicitely checking that deposit exists by making it to this point.
|
|
1277
|
-
if (!
|
|
1129
|
+
if (!deposit) {
|
|
1278
1130
|
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
1279
1131
|
}
|
|
1280
1132
|
// We should never push fast fills involving lite chains here because slow fill requests for them are invalid:
|
|
1281
1133
|
assert(
|
|
1282
|
-
_canCreateSlowFillLeaf(
|
|
1134
|
+
_canCreateSlowFillLeaf(deposit),
|
|
1283
1135
|
"fastFillsReplacingSlowFills should contain only deposits that can be slow filled"
|
|
1284
1136
|
);
|
|
1285
1137
|
const destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
@@ -1289,7 +1141,7 @@ export class BundleDataClient {
|
|
|
1289
1141
|
!slowFillRequest ||
|
|
1290
1142
|
slowFillRequest.blockNumber < destinationBlockRange[0]
|
|
1291
1143
|
) {
|
|
1292
|
-
validatedBundleUnexecutableSlowFills.push(
|
|
1144
|
+
validatedBundleUnexecutableSlowFills.push(deposit);
|
|
1293
1145
|
}
|
|
1294
1146
|
});
|
|
1295
1147
|
}
|
|
@@ -1303,19 +1155,15 @@ export class BundleDataClient {
|
|
|
1303
1155
|
// For all deposits older than this bundle, we need to check if they expired in this bundle and if they did,
|
|
1304
1156
|
// whether there was a slow fill created for it in a previous bundle that is now unexecutable and replaced
|
|
1305
1157
|
// by a new expired deposit refund.
|
|
1306
|
-
await forEachAsync(olderDepositHashes, async (
|
|
1307
|
-
const {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
throw new Error("Deposit should exist in relay hash dictionary.");
|
|
1311
|
-
}
|
|
1312
|
-
const deposit = deposits[index];
|
|
1313
|
-
const { destinationChainId } = deposit;
|
|
1158
|
+
await forEachAsync(olderDepositHashes, async (relayDataHash) => {
|
|
1159
|
+
const { deposit, slowFillRequest, fill } = v3RelayHashes[relayDataHash];
|
|
1160
|
+
assert(isDefined(deposit), "Deposit should exist in relay hash dictionary.");
|
|
1161
|
+
const { destinationChainId } = deposit!;
|
|
1314
1162
|
const destinationBlockRange = getBlockRangeForChain(blockRangesForChains, destinationChainId, chainIds);
|
|
1315
1163
|
|
|
1316
1164
|
// Only look for deposits that were mined before this bundle and that are newly expired.
|
|
1317
1165
|
// If the fill deadline is lower than the bundle start block on the destination chain, then
|
|
1318
|
-
// we should assume it was refunded in a previous bundle.
|
|
1166
|
+
// we should assume it was marked "newly expired" and refunded in a previous bundle.
|
|
1319
1167
|
if (
|
|
1320
1168
|
// If there is a valid fill that we saw matching this deposit, then it does not need a refund.
|
|
1321
1169
|
!fill &&
|
|
@@ -1359,7 +1207,7 @@ export class BundleDataClient {
|
|
|
1359
1207
|
validatedBundleV3Fills.length > 0
|
|
1360
1208
|
? this.clients.hubPoolClient.batchComputeRealizedLpFeePct(
|
|
1361
1209
|
validatedBundleV3Fills.map((fill) => {
|
|
1362
|
-
const matchedDeposit = v3RelayHashes[this.getRelayHashFromEvent(fill)].
|
|
1210
|
+
const matchedDeposit = v3RelayHashes[this.getRelayHashFromEvent(fill)].deposit;
|
|
1363
1211
|
assert(isDefined(matchedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
1364
1212
|
const { chainToSendRefundTo: paymentChainId } = getRefundInformationFromFill(
|
|
1365
1213
|
fill,
|
|
@@ -1403,7 +1251,7 @@ export class BundleDataClient {
|
|
|
1403
1251
|
});
|
|
1404
1252
|
v3FillLpFees.forEach(({ realizedLpFeePct }, idx) => {
|
|
1405
1253
|
const fill = validatedBundleV3Fills[idx];
|
|
1406
|
-
const associatedDeposit = v3RelayHashes[this.getRelayHashFromEvent(fill)].
|
|
1254
|
+
const associatedDeposit = v3RelayHashes[this.getRelayHashFromEvent(fill)].deposit;
|
|
1407
1255
|
assert(isDefined(associatedDeposit), "Deposit should exist in relay hash dictionary.");
|
|
1408
1256
|
const { chainToSendRefundTo, repaymentToken } = getRefundInformationFromFill(
|
|
1409
1257
|
fill,
|
|
@@ -1412,19 +1260,10 @@ export class BundleDataClient {
|
|
|
1412
1260
|
chainIds,
|
|
1413
1261
|
associatedDeposit!.fromLiteChain
|
|
1414
1262
|
);
|
|
1415
|
-
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken
|
|
1263
|
+
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken);
|
|
1416
1264
|
});
|
|
1417
1265
|
v3SlowFillLpFees.forEach(({ realizedLpFeePct: lpFeePct }, idx) => {
|
|
1418
1266
|
const deposit = validatedBundleSlowFills[idx];
|
|
1419
|
-
// We should not create slow fill leaves for duplicate deposit hashes and we should only create a slow
|
|
1420
|
-
// fill leaf for the first deposit (the quote timestamp of the deposit determines the LP fee, so its
|
|
1421
|
-
// important we pick out the correct deposit). Deposits are pushed into validatedBundleSlowFills in ascending
|
|
1422
|
-
// order so the following slice will only match the first deposit.
|
|
1423
|
-
const relayDataHash = this.getRelayHashFromEvent(deposit);
|
|
1424
|
-
if (validatedBundleSlowFills.slice(0, idx).some((d) => this.getRelayHashFromEvent(d) === relayDataHash)) {
|
|
1425
|
-
return;
|
|
1426
|
-
}
|
|
1427
|
-
assert(!_depositIsExpired(deposit), "Cannot create slow fill leaf for expired deposit.");
|
|
1428
1267
|
updateBundleSlowFills(bundleSlowFillsV3, { ...deposit, lpFeePct });
|
|
1429
1268
|
});
|
|
1430
1269
|
v3UnexecutableSlowFillLpFees.forEach(({ realizedLpFeePct: lpFeePct }, idx) => {
|
|
@@ -1435,6 +1274,7 @@ export class BundleDataClient {
|
|
|
1435
1274
|
const v3SpokeEventsReadable = prettyPrintV3SpokePoolEvents(
|
|
1436
1275
|
bundleDepositsV3,
|
|
1437
1276
|
bundleFillsV3,
|
|
1277
|
+
bundleInvalidFillsV3,
|
|
1438
1278
|
bundleSlowFillsV3,
|
|
1439
1279
|
expiredDepositsToRefundV3,
|
|
1440
1280
|
unexecutableSlowFills
|
|
@@ -1449,15 +1289,6 @@ export class BundleDataClient {
|
|
|
1449
1289
|
});
|
|
1450
1290
|
}
|
|
1451
1291
|
|
|
1452
|
-
if (bundleUnrepayableFillsV3.length > 0) {
|
|
1453
|
-
this.logger.debug({
|
|
1454
|
-
at: "BundleDataClient#loadData",
|
|
1455
|
-
message: "Finished loading V3 spoke pool data and found some unrepayable V3 fills in range",
|
|
1456
|
-
blockRangesForChains,
|
|
1457
|
-
bundleUnrepayableFillsV3,
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
1292
|
this.logger.debug({
|
|
1462
1293
|
at: "BundleDataClient#loadDataFromScratch",
|
|
1463
1294
|
message: `Computed bundle data in ${Math.round(performance.now() - start) / 1000}s.`,
|
|
@@ -1477,7 +1308,7 @@ export class BundleDataClient {
|
|
|
1477
1308
|
// keccak256 hash of the relay data, which can be used as input into the on-chain `fillStatuses()` function in the
|
|
1478
1309
|
// spoke pool contract. However, this internal function is used to uniquely identify a bridging event
|
|
1479
1310
|
// for speed since its easier to build a string from the event data than to hash it.
|
|
1480
|
-
|
|
1311
|
+
private getRelayHashFromEvent(event: V3DepositWithBlock | V3FillWithBlock | SlowFillRequestWithBlock): string {
|
|
1481
1312
|
return `${event.depositor}-${event.recipient}-${event.exclusiveRelayer}-${event.inputToken}-${event.outputToken}-${
|
|
1482
1313
|
event.inputAmount
|
|
1483
1314
|
}-${event.outputAmount}-${event.originChainId}-${event.depositId.toString()}-${event.fillDeadline}-${
|
|
@@ -1485,18 +1316,6 @@ export class BundleDataClient {
|
|
|
1485
1316
|
}-${event.message}-${event.destinationChainId}`;
|
|
1486
1317
|
}
|
|
1487
1318
|
|
|
1488
|
-
protected async findMatchingFillEvent(
|
|
1489
|
-
deposit: DepositWithBlock,
|
|
1490
|
-
spokePoolClient: SpokePoolClient
|
|
1491
|
-
): Promise<FillWithBlock | undefined> {
|
|
1492
|
-
return await findFillEvent(
|
|
1493
|
-
spokePoolClient.spokePool,
|
|
1494
|
-
deposit,
|
|
1495
|
-
spokePoolClient.deploymentBlock,
|
|
1496
|
-
spokePoolClient.latestBlockSearched
|
|
1497
|
-
);
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
1319
|
async getBundleBlockTimestamps(
|
|
1501
1320
|
chainIds: number[],
|
|
1502
1321
|
blockRangesForChains: number[][],
|
|
@@ -1522,26 +1341,13 @@ export class BundleDataClient {
|
|
|
1522
1341
|
// will usually be called in production with block ranges that were validated by
|
|
1523
1342
|
// DataworkerUtils.blockRangesAreInvalidForSpokeClients.
|
|
1524
1343
|
const startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestBlockSearched);
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
// in exactly one bundle, therefore we must make sure that the bundle block timestamp for one bundle's
|
|
1528
|
-
// end block is exactly equal to the bundle block timestamp for the next bundle's start block. This way
|
|
1529
|
-
// there are no gaps in block timestamps between bundles.
|
|
1530
|
-
const endBlockForChain = Math.min(_endBlockForChain + 1, spokePoolClient.latestBlockSearched);
|
|
1531
|
-
const [startTime, _endTime] = [
|
|
1344
|
+
const endBlockForChain = Math.min(_endBlockForChain, spokePoolClient.latestBlockSearched);
|
|
1345
|
+
const [startTime, endTime] = [
|
|
1532
1346
|
await spokePoolClient.getTimestampForBlock(startBlockForChain),
|
|
1533
1347
|
await spokePoolClient.getTimestampForBlock(endBlockForChain),
|
|
1534
1348
|
];
|
|
1535
|
-
// @dev similar to reasoning above to ensure no gaps between bundle block range timestamps and also
|
|
1536
|
-
// no overlap, subtract 1 from the end time.
|
|
1537
|
-
const endBlockDelta = endBlockForChain > startBlockForChain ? 1 : 0;
|
|
1538
|
-
const endTime = Math.max(0, _endTime - endBlockDelta);
|
|
1539
|
-
|
|
1540
1349
|
// Sanity checks:
|
|
1541
|
-
assert(
|
|
1542
|
-
endTime >= startTime,
|
|
1543
|
-
`End time for block ${endBlockForChain} should be greater than start time for block ${startBlockForChain}: ${endTime} >= ${startTime}.`
|
|
1544
|
-
);
|
|
1350
|
+
assert(endTime >= startTime, "End time should be greater than start time.");
|
|
1545
1351
|
assert(
|
|
1546
1352
|
startBlockForChain === 0 || startTime > 0,
|
|
1547
1353
|
"Start timestamp must be greater than 0 if the start block is greater than 0."
|