@across-protocol/sdk 3.4.12 → 3.4.13
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/utils/SuperstructUtils.d.ts +12 -10
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +3 -3
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/cjs/clients/SpokePoolClient.d.ts +12 -12
- package/dist/cjs/clients/SpokePoolClient.js +17 -15
- package/dist/cjs/clients/SpokePoolClient.js.map +1 -1
- package/dist/cjs/clients/mocks/MockSpokePoolClient.d.ts +5 -4
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js +7 -7
- package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/cjs/constants.d.ts +2 -2
- package/dist/cjs/constants.js +3 -3
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/interfaces/SpokePool.d.ts +2 -2
- package/dist/cjs/utils/BigNumberUtils.d.ts +1 -0
- package/dist/cjs/utils/BigNumberUtils.js +5 -1
- package/dist/cjs/utils/BigNumberUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.js +2 -2
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/cjs/utils/EventUtils.js +4 -0
- package/dist/cjs/utils/EventUtils.js.map +1 -1
- package/dist/cjs/utils/SpokeUtils.d.ts +5 -3
- package/dist/cjs/utils/SpokeUtils.js +15 -8
- package/dist/cjs/utils/SpokeUtils.js.map +1 -1
- package/dist/cjs/utils/ValidatorUtils.js +1 -1
- package/dist/cjs/utils/ValidatorUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +12 -10
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +4 -4
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
- package/dist/esm/clients/SpokePoolClient.d.ts +12 -12
- package/dist/esm/clients/SpokePoolClient.js +18 -16
- package/dist/esm/clients/SpokePoolClient.js.map +1 -1
- package/dist/esm/clients/mocks/MockSpokePoolClient.d.ts +5 -4
- package/dist/esm/clients/mocks/MockSpokePoolClient.js +8 -8
- package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
- package/dist/esm/constants.d.ts +2 -2
- package/dist/esm/constants.js +2 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/interfaces/SpokePool.d.ts +2 -2
- package/dist/esm/utils/BigNumberUtils.d.ts +8 -0
- package/dist/esm/utils/BigNumberUtils.js +10 -0
- package/dist/esm/utils/BigNumberUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.js +2 -2
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/esm/utils/EventUtils.js +8 -0
- package/dist/esm/utils/EventUtils.js.map +1 -1
- package/dist/esm/utils/SpokeUtils.d.ts +5 -3
- package/dist/esm/utils/SpokeUtils.js +17 -9
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/esm/utils/ValidatorUtils.js +1 -1
- package/dist/esm/utils/ValidatorUtils.js.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +12 -10
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts.map +1 -1
- package/dist/types/clients/SpokePoolClient.d.ts +12 -12
- package/dist/types/clients/SpokePoolClient.d.ts.map +1 -1
- package/dist/types/clients/mocks/MockSpokePoolClient.d.ts +5 -4
- package/dist/types/clients/mocks/MockSpokePoolClient.d.ts.map +1 -1
- package/dist/types/constants.d.ts +2 -2
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/interfaces/SpokePool.d.ts +2 -2
- package/dist/types/interfaces/SpokePool.d.ts.map +1 -1
- package/dist/types/utils/BigNumberUtils.d.ts +8 -0
- package/dist/types/utils/BigNumberUtils.d.ts.map +1 -1
- package/dist/types/utils/EventUtils.d.ts.map +1 -1
- package/dist/types/utils/SpokeUtils.d.ts +5 -3
- package/dist/types/utils/SpokeUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/clients/BundleDataClient/utils/SuperstructUtils.ts +4 -2
- package/src/clients/SpokePoolClient.ts +27 -23
- package/src/clients/mocks/MockSpokePoolClient.ts +11 -11
- package/src/constants.ts +2 -2
- package/src/interfaces/SpokePool.ts +2 -2
- package/src/utils/BigNumberUtils.ts +11 -0
- package/src/utils/DepositUtils.ts +2 -2
- package/src/utils/EventUtils.ts +8 -0
- package/src/utils/SpokeUtils.ts +25 -14
- package/src/utils/ValidatorUtils.ts +1 -1
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
getRelayDataHash,
|
|
13
13
|
isDefined,
|
|
14
14
|
toBN,
|
|
15
|
+
bnOne,
|
|
16
|
+
isUnsafeDepositId,
|
|
15
17
|
} from "../utils";
|
|
16
18
|
import {
|
|
17
19
|
paginatedEventQuery,
|
|
@@ -46,8 +48,8 @@ type SpokePoolUpdateSuccess = {
|
|
|
46
48
|
success: true;
|
|
47
49
|
currentTime: number;
|
|
48
50
|
oldestTime: number;
|
|
49
|
-
firstDepositId:
|
|
50
|
-
latestDepositId:
|
|
51
|
+
firstDepositId: BigNumber;
|
|
52
|
+
latestDepositId: BigNumber;
|
|
51
53
|
events: Log[][];
|
|
52
54
|
searchEndBlock: number;
|
|
53
55
|
};
|
|
@@ -66,7 +68,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
66
68
|
protected oldestTime = 0;
|
|
67
69
|
protected depositHashes: { [depositHash: string]: DepositWithBlock } = {};
|
|
68
70
|
protected depositHashesToFills: { [depositHash: string]: FillWithBlock[] } = {};
|
|
69
|
-
protected speedUps: { [depositorAddress: string]: { [depositId:
|
|
71
|
+
protected speedUps: { [depositorAddress: string]: { [depositId: string]: SpeedUpWithBlock[] } } = {};
|
|
70
72
|
protected slowFillRequests: { [relayDataHash: string]: SlowFillRequestWithBlock } = {};
|
|
71
73
|
protected depositRoutes: { [originToken: string]: { [DestinationChainId: number]: boolean } } = {};
|
|
72
74
|
protected tokensBridged: TokensBridged[] = [];
|
|
@@ -74,10 +76,10 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
74
76
|
protected relayerRefundExecutions: RelayerRefundExecutionWithBlock[] = [];
|
|
75
77
|
protected queryableEventNames: string[] = [];
|
|
76
78
|
protected configStoreClient: AcrossConfigStoreClient | undefined;
|
|
77
|
-
public earliestDepositIdQueried =
|
|
78
|
-
public latestDepositIdQueried =
|
|
79
|
-
public firstDepositIdForSpokePool =
|
|
80
|
-
public lastDepositIdForSpokePool =
|
|
79
|
+
public earliestDepositIdQueried = MAX_BIG_INT;
|
|
80
|
+
public latestDepositIdQueried = bnZero;
|
|
81
|
+
public firstDepositIdForSpokePool = MAX_BIG_INT;
|
|
82
|
+
public lastDepositIdForSpokePool = MAX_BIG_INT;
|
|
81
83
|
public fills: { [OriginChainId: number]: FillWithBlock[] } = {};
|
|
82
84
|
|
|
83
85
|
/**
|
|
@@ -232,7 +234,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
232
234
|
*/
|
|
233
235
|
public appendMaxSpeedUpSignatureToDeposit(deposit: DepositWithBlock): DepositWithBlock {
|
|
234
236
|
const { depositId, depositor } = deposit;
|
|
235
|
-
const speedups = this.speedUps[depositor]?.[depositId];
|
|
237
|
+
const speedups = this.speedUps[depositor]?.[depositId.toString()];
|
|
236
238
|
if (!isDefined(speedups) || speedups.length === 0) {
|
|
237
239
|
return deposit;
|
|
238
240
|
}
|
|
@@ -265,7 +267,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
265
267
|
* @param depositId The unique ID of the deposit being queried.
|
|
266
268
|
* @returns The corresponding deposit if found, undefined otherwise.
|
|
267
269
|
*/
|
|
268
|
-
public getDeposit(depositId:
|
|
270
|
+
public getDeposit(depositId: BigNumber): DepositWithBlock | undefined {
|
|
269
271
|
const depositHash = this.getDepositHash({ depositId, originChainId: this.chainId });
|
|
270
272
|
return this.depositHashes[depositHash];
|
|
271
273
|
}
|
|
@@ -295,7 +297,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
295
297
|
* Retrieves speed up requests grouped by depositor and depositId.
|
|
296
298
|
* @returns A mapping of depositor addresses to deposit ids with their corresponding speed up requests.
|
|
297
299
|
*/
|
|
298
|
-
public getSpeedUps(): { [depositorAddress: string]: { [depositId:
|
|
300
|
+
public getSpeedUps(): { [depositorAddress: string]: { [depositId: string]: SpeedUpWithBlock[] } } {
|
|
299
301
|
return this.speedUps;
|
|
300
302
|
}
|
|
301
303
|
|
|
@@ -365,7 +367,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
365
367
|
);
|
|
366
368
|
|
|
367
369
|
// Log any invalid deposits with same deposit id but different params.
|
|
368
|
-
const invalidFillsForDeposit = invalidFills.filter((x) => x.depositId
|
|
370
|
+
const invalidFillsForDeposit = invalidFills.filter((x) => x.depositId.eq(deposit.depositId));
|
|
369
371
|
if (invalidFillsForDeposit.length > 0) {
|
|
370
372
|
this.logger.warn({
|
|
371
373
|
at: "SpokePoolClient",
|
|
@@ -396,7 +398,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
396
398
|
* @note This hash is used to match deposits and fills together.
|
|
397
399
|
* @note This hash takes the form of: `${depositId}-${originChainId}`.
|
|
398
400
|
*/
|
|
399
|
-
public getDepositHash(event: { depositId:
|
|
401
|
+
public getDepositHash(event: { depositId: BigNumber; originChainId: number }): string {
|
|
400
402
|
return `${event.depositId}-${event.originChainId}`;
|
|
401
403
|
}
|
|
402
404
|
|
|
@@ -405,7 +407,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
405
407
|
* @param blockTag The block number to search for the deposit ID at.
|
|
406
408
|
* @returns The deposit ID.
|
|
407
409
|
*/
|
|
408
|
-
public _getDepositIdAtBlock(blockTag: number): Promise<
|
|
410
|
+
public _getDepositIdAtBlock(blockTag: number): Promise<BigNumber> {
|
|
409
411
|
return getDepositIdAtBlock(this.spokePool as SpokePool, blockTag);
|
|
410
412
|
}
|
|
411
413
|
|
|
@@ -438,10 +440,11 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
438
440
|
*/
|
|
439
441
|
protected async _update(eventsToQuery: string[]): Promise<SpokePoolUpdate> {
|
|
440
442
|
// Find the earliest known depositId. This assumes no deposits were placed in the deployment block.
|
|
441
|
-
let firstDepositId
|
|
442
|
-
if (firstDepositId
|
|
443
|
+
let firstDepositId = this.firstDepositIdForSpokePool;
|
|
444
|
+
if (firstDepositId.eq(MAX_BIG_INT)) {
|
|
443
445
|
firstDepositId = await this.spokePool.numberOfDeposits({ blockTag: this.deploymentBlock });
|
|
444
|
-
|
|
446
|
+
firstDepositId = BigNumber.from(firstDepositId); // Cast input to a big number.
|
|
447
|
+
if (!BigNumber.isBigNumber(firstDepositId) || firstDepositId.lt(bnZero)) {
|
|
445
448
|
throw new Error(`SpokePoolClient::update: Invalid first deposit id (${firstDepositId})`);
|
|
446
449
|
}
|
|
447
450
|
}
|
|
@@ -491,9 +494,10 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
491
494
|
]);
|
|
492
495
|
this.log("debug", `Time to query new events from RPC for ${this.chainId}: ${Date.now() - timerStart} ms`);
|
|
493
496
|
|
|
494
|
-
const [currentTime,
|
|
497
|
+
const [currentTime, _numberOfDeposits] = multicallFunctions.map(
|
|
495
498
|
(fn, idx) => spokePool.interface.decodeFunctionResult(fn, multicallOutput[idx])[0]
|
|
496
499
|
);
|
|
500
|
+
const _latestDepositId = BigNumber.from(_numberOfDeposits).sub(bnOne);
|
|
497
501
|
|
|
498
502
|
if (!BigNumber.isBigNumber(currentTime) || currentTime.lt(this.currentTime)) {
|
|
499
503
|
const errMsg = BigNumber.isBigNumber(currentTime)
|
|
@@ -510,7 +514,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
510
514
|
currentTime: currentTime.toNumber(), // uint32
|
|
511
515
|
oldestTime: oldestTime.toNumber(),
|
|
512
516
|
firstDepositId,
|
|
513
|
-
latestDepositId:
|
|
517
|
+
latestDepositId: _latestDepositId.gt(bnZero) ? _latestDepositId : bnZero,
|
|
514
518
|
searchEndBlock: searchConfig.toBlock,
|
|
515
519
|
events,
|
|
516
520
|
};
|
|
@@ -579,10 +583,10 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
579
583
|
}
|
|
580
584
|
assign(this.depositHashes, [this.getDepositHash(deposit)], deposit);
|
|
581
585
|
|
|
582
|
-
if (deposit.depositId
|
|
586
|
+
if (deposit.depositId.lt(this.earliestDepositIdQueried) && !isUnsafeDepositId(deposit.depositId)) {
|
|
583
587
|
this.earliestDepositIdQueried = deposit.depositId;
|
|
584
588
|
}
|
|
585
|
-
if (deposit.depositId
|
|
589
|
+
if (deposit.depositId.gt(this.latestDepositIdQueried) && !isUnsafeDepositId(deposit.depositId)) {
|
|
586
590
|
this.latestDepositIdQueried = deposit.depositId;
|
|
587
591
|
}
|
|
588
592
|
}
|
|
@@ -594,7 +598,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
594
598
|
|
|
595
599
|
for (const event of speedUpEvents) {
|
|
596
600
|
const speedUp = { ...spreadEventWithBlockNumber(event), originChainId: this.chainId } as SpeedUpWithBlock;
|
|
597
|
-
assign(this.speedUps, [speedUp.depositor, speedUp.depositId], [speedUp]);
|
|
601
|
+
assign(this.speedUps, [speedUp.depositor, speedUp.depositId.toString()], [speedUp]);
|
|
598
602
|
|
|
599
603
|
// Find deposit hash matching this speed up event and update the deposit data associated with the hash,
|
|
600
604
|
// if the hash+data exists.
|
|
@@ -778,7 +782,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
778
782
|
return this.oldestTime;
|
|
779
783
|
}
|
|
780
784
|
|
|
781
|
-
async findDeposit(depositId:
|
|
785
|
+
async findDeposit(depositId: BigNumber, destinationChainId: number): Promise<DepositWithBlock> {
|
|
782
786
|
// Binary search for event search bounds. This way we can get the blocks before and after the deposit with
|
|
783
787
|
// deposit ID = fill.depositId and use those blocks to optimize the search for that deposit.
|
|
784
788
|
// Stop searches after a maximum # of searches to limit number of eth_call requests. Make an
|
|
@@ -807,7 +811,7 @@ export class SpokePoolClient extends BaseAbstractClient {
|
|
|
807
811
|
);
|
|
808
812
|
const tStop = Date.now();
|
|
809
813
|
|
|
810
|
-
const event = query.find(({ args }) => args["depositId"]
|
|
814
|
+
const event = query.find(({ args }) => args["depositId"].eq(depositId));
|
|
811
815
|
if (event === undefined) {
|
|
812
816
|
const srcChain = getNetworkName(this.chainId);
|
|
813
817
|
const dstChain = getNetworkName(destinationChainId);
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
SlowFillLeaf,
|
|
15
15
|
SpeedUp,
|
|
16
16
|
} from "../../interfaces";
|
|
17
|
-
import { toBN, toBNWei, getCurrentTime, randomAddress } from "../../utils";
|
|
17
|
+
import { toBN, toBNWei, getCurrentTime, randomAddress, BigNumber, bnZero, bnOne, bnMax } from "../../utils";
|
|
18
18
|
import { SpokePoolClient, SpokePoolUpdate } from "../SpokePoolClient";
|
|
19
19
|
import { HubPoolClient } from "../HubPoolClient";
|
|
20
20
|
import { EventManager, EventOverrides, getEventManager } from "./MockEvents";
|
|
@@ -26,8 +26,8 @@ export class MockSpokePoolClient extends SpokePoolClient {
|
|
|
26
26
|
public eventManager: EventManager;
|
|
27
27
|
private destinationTokenForChainOverride: Record<number, string> = {};
|
|
28
28
|
// Allow tester to set the numberOfDeposits() returned by SpokePool at a block height.
|
|
29
|
-
public depositIdAtBlock:
|
|
30
|
-
public numberOfDeposits =
|
|
29
|
+
public depositIdAtBlock: BigNumber[] = [];
|
|
30
|
+
public numberOfDeposits = bnZero;
|
|
31
31
|
|
|
32
32
|
constructor(
|
|
33
33
|
logger: winston.Logger,
|
|
@@ -57,21 +57,21 @@ export class MockSpokePoolClient extends SpokePoolClient {
|
|
|
57
57
|
this.latestBlockSearched = blockNumber;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
setDepositIds(_depositIds:
|
|
60
|
+
setDepositIds(_depositIds: BigNumber[]): void {
|
|
61
61
|
this.depositIdAtBlock = [];
|
|
62
62
|
if (_depositIds.length === 0) {
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
let lastDepositId = _depositIds[0];
|
|
66
66
|
for (let i = 0; i < _depositIds.length; i++) {
|
|
67
|
-
if (_depositIds[i]
|
|
67
|
+
if (_depositIds[i].lt(lastDepositId)) {
|
|
68
68
|
throw new Error("deposit ID must be equal to or greater than previous");
|
|
69
69
|
}
|
|
70
70
|
this.depositIdAtBlock[i] = _depositIds[i];
|
|
71
71
|
lastDepositId = _depositIds[i];
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
_getDepositIdAtBlock(blockTag: number): Promise<
|
|
74
|
+
_getDepositIdAtBlock(blockTag: number): Promise<BigNumber> {
|
|
75
75
|
return Promise.resolve(this.depositIdAtBlock[blockTag]);
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -96,13 +96,13 @@ export class MockSpokePoolClient extends SpokePoolClient {
|
|
|
96
96
|
// Update latestDepositIdQueried.
|
|
97
97
|
const idx = eventsToQuery.indexOf("V3FundsDeposited");
|
|
98
98
|
const latestDepositId = (events[idx] ?? []).reduce(
|
|
99
|
-
(depositId, event) =>
|
|
99
|
+
(depositId, event) => bnMax(depositId, event.args["depositId"] ?? bnZero),
|
|
100
100
|
this.latestDepositIdQueried
|
|
101
101
|
);
|
|
102
102
|
|
|
103
103
|
return Promise.resolve({
|
|
104
104
|
success: true,
|
|
105
|
-
firstDepositId:
|
|
105
|
+
firstDepositId: bnZero,
|
|
106
106
|
latestDepositId,
|
|
107
107
|
currentTime,
|
|
108
108
|
oldestTime: 0,
|
|
@@ -122,8 +122,8 @@ export class MockSpokePoolClient extends SpokePoolClient {
|
|
|
122
122
|
const { blockNumber, transactionIndex } = deposit;
|
|
123
123
|
let { depositId, depositor, destinationChainId, inputToken, inputAmount, outputToken, outputAmount } = deposit;
|
|
124
124
|
depositId ??= this.numberOfDeposits;
|
|
125
|
-
assert(depositId
|
|
126
|
-
this.numberOfDeposits = depositId
|
|
125
|
+
assert(depositId.gte(this.numberOfDeposits), `${depositId} < ${this.numberOfDeposits}`);
|
|
126
|
+
this.numberOfDeposits = depositId.add(bnOne);
|
|
127
127
|
|
|
128
128
|
destinationChainId ??= random(1, 42161, false);
|
|
129
129
|
depositor ??= randomAddress();
|
|
@@ -168,7 +168,7 @@ export class MockSpokePoolClient extends SpokePoolClient {
|
|
|
168
168
|
const { blockNumber, transactionIndex } = fill;
|
|
169
169
|
let { originChainId, depositId, inputToken, inputAmount, outputAmount, fillDeadline, relayer } = fill;
|
|
170
170
|
originChainId ??= random(1, 42161, false);
|
|
171
|
-
depositId ??= random(1, 100_000, false);
|
|
171
|
+
depositId ??= BigNumber.from(random(1, 100_000, false));
|
|
172
172
|
inputToken ??= randomAddress();
|
|
173
173
|
inputAmount ??= toBNWei(random(1, 1000, false));
|
|
174
174
|
outputAmount ??= inputAmount;
|
package/src/constants.ts
CHANGED
|
@@ -10,7 +10,7 @@ export {
|
|
|
10
10
|
TOKEN_SYMBOLS_MAP,
|
|
11
11
|
} from "@across-protocol/constants";
|
|
12
12
|
|
|
13
|
-
export const { AddressZero: ZERO_ADDRESS } = ethersConstants;
|
|
13
|
+
export const { AddressZero: ZERO_ADDRESS, HashZero: ZERO_BYTES } = ethersConstants;
|
|
14
14
|
|
|
15
15
|
// 2^96 - 1 is a conservative erc20 max allowance.
|
|
16
16
|
export const MAX_SAFE_ALLOWANCE = "79228162514264337593543950335";
|
|
@@ -33,7 +33,7 @@ export const TRANSFER_THRESHOLD_MAX_CONFIG_STORE_VERSION = 1;
|
|
|
33
33
|
export const ARWEAVE_TAG_APP_NAME = "across-protocol";
|
|
34
34
|
|
|
35
35
|
// A hardcoded version number used, by default, to tag all Arweave records.
|
|
36
|
-
export const ARWEAVE_TAG_APP_VERSION =
|
|
36
|
+
export const ARWEAVE_TAG_APP_VERSION = 3;
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* A default list of chain Ids that the protocol supports. This is outlined
|
|
@@ -10,7 +10,7 @@ export interface RelayData {
|
|
|
10
10
|
originChainId: number;
|
|
11
11
|
depositor: string;
|
|
12
12
|
recipient: string;
|
|
13
|
-
depositId:
|
|
13
|
+
depositId: BigNumber;
|
|
14
14
|
inputToken: string;
|
|
15
15
|
inputAmount: BigNumber;
|
|
16
16
|
outputToken: string;
|
|
@@ -67,7 +67,7 @@ export interface FillWithBlock extends Fill, SortableEvent {}
|
|
|
67
67
|
export interface SpeedUp {
|
|
68
68
|
depositor: string;
|
|
69
69
|
depositorSignature: string;
|
|
70
|
-
depositId:
|
|
70
|
+
depositId: BigNumber;
|
|
71
71
|
originChainId: number;
|
|
72
72
|
updatedRecipient: string;
|
|
73
73
|
updatedOutputAmount: BigNumber;
|
|
@@ -62,3 +62,14 @@ export const toBN = (num: BigNumberish, rounding: "floor" | "round" | "ceil" = "
|
|
|
62
62
|
// Otherwise, it is a string int and we can parse it directly.
|
|
63
63
|
return BigNumber.from(num.toString());
|
|
64
64
|
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Compares two BigNumbers and returns the maximum. Order does not matter.
|
|
68
|
+
*
|
|
69
|
+
* @param val The first BigNumber to compare.
|
|
70
|
+
* @param cmp The second BigNumber to compare.
|
|
71
|
+
* @returns The greater of the two BigNumbers.
|
|
72
|
+
*/
|
|
73
|
+
export const bnMax = (val: BigNumber, cmp: BigNumber) => {
|
|
74
|
+
return val.gt(cmp) ? val : cmp;
|
|
75
|
+
};
|
|
@@ -52,7 +52,7 @@ export async function queryHistoricalDepositForFill(
|
|
|
52
52
|
|
|
53
53
|
const { depositId } = fill;
|
|
54
54
|
let { firstDepositIdForSpokePool: lowId, lastDepositIdForSpokePool: highId } = spokePoolClient;
|
|
55
|
-
if (depositId
|
|
55
|
+
if (depositId.lt(lowId) || depositId.gt(highId)) {
|
|
56
56
|
return {
|
|
57
57
|
found: false,
|
|
58
58
|
code: InvalidFill.DepositIdInvalid,
|
|
@@ -61,7 +61,7 @@ export async function queryHistoricalDepositForFill(
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
({ earliestDepositIdQueried: lowId, latestDepositIdQueried: highId } = spokePoolClient);
|
|
64
|
-
if (depositId
|
|
64
|
+
if (depositId.gte(lowId) && depositId.lte(highId)) {
|
|
65
65
|
const originChain = getNetworkName(fill.originChainId);
|
|
66
66
|
const deposit = spokePoolClient.getDeposit(depositId);
|
|
67
67
|
if (isDefined(deposit)) {
|
package/src/utils/EventUtils.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Result } from "@ethersproject/abi";
|
|
|
3
3
|
import { Contract, Event, EventFilter } from "ethers";
|
|
4
4
|
import { Log, SortableEvent } from "../interfaces";
|
|
5
5
|
import { delay } from "./common";
|
|
6
|
+
import { isDefined, toBN, BigNumberish } from "./";
|
|
6
7
|
|
|
7
8
|
const maxRetries = 3;
|
|
8
9
|
const retrySleepTime = 10;
|
|
@@ -58,6 +59,13 @@ export function spreadEvent(args: Result | Record<string, unknown>): { [key: str
|
|
|
58
59
|
if (returnedObject.rootBundleId) {
|
|
59
60
|
returnedObject.rootBundleId = Number(returnedObject.rootBundleId);
|
|
60
61
|
}
|
|
62
|
+
// If depositId is included in the event, cast it to a BigNumber. Need to check if it is defined since the deposit ID can
|
|
63
|
+
// be 0, which would still make this evaluate as false.
|
|
64
|
+
if (isDefined(returnedObject.depositId)) {
|
|
65
|
+
// Assuming a numeric output, we can safely cast the unknown to BigNumberish since the depositId will either be a uint32 (and therefore a TypeScript `number`),
|
|
66
|
+
// or a uint256 (and therefore an ethers BigNumber).
|
|
67
|
+
returnedObject.depositId = toBN(returnedObject.depositId as BigNumberish);
|
|
68
|
+
}
|
|
61
69
|
|
|
62
70
|
return returnedObject;
|
|
63
71
|
}
|
package/src/utils/SpokeUtils.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
2
|
import { BytesLike, Contract, PopulatedTransaction, providers, utils as ethersUtils } from "ethers";
|
|
3
|
-
import { CHAIN_IDs, MAX_SAFE_DEPOSIT_ID, ZERO_ADDRESS } from "../constants";
|
|
3
|
+
import { CHAIN_IDs, MAX_SAFE_DEPOSIT_ID, ZERO_ADDRESS, ZERO_BYTES } from "../constants";
|
|
4
4
|
import { Deposit, Fill, FillStatus, RelayData, SlowFillRequest } from "../interfaces";
|
|
5
5
|
import { SpokePoolClient } from "../clients";
|
|
6
6
|
import { chunk } from "./ArrayUtils";
|
|
7
|
-
import { BigNumber, toBN } from "./BigNumberUtils";
|
|
7
|
+
import { BigNumber, toBN, bnOne, bnZero } from "./BigNumberUtils";
|
|
8
8
|
import { isDefined } from "./TypeGuards";
|
|
9
9
|
import { getNetworkName } from "./NetworkUtils";
|
|
10
10
|
|
|
@@ -70,7 +70,7 @@ export function populateV3Relay(
|
|
|
70
70
|
* // where the deposit with deposit ID = targetDepositId was created.
|
|
71
71
|
*/
|
|
72
72
|
export async function getBlockRangeForDepositId(
|
|
73
|
-
targetDepositId:
|
|
73
|
+
targetDepositId: BigNumber,
|
|
74
74
|
initLow: number,
|
|
75
75
|
initHigh: number,
|
|
76
76
|
maxSearches: number,
|
|
@@ -79,6 +79,12 @@ export async function getBlockRangeForDepositId(
|
|
|
79
79
|
low: number;
|
|
80
80
|
high: number;
|
|
81
81
|
}> {
|
|
82
|
+
// We can only perform this search when we have a safe deposit ID.
|
|
83
|
+
if (isUnsafeDepositId(targetDepositId))
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Target deposit ID ${targetDepositId} is deterministic and therefore unresolvable via a binary search.`
|
|
86
|
+
);
|
|
87
|
+
|
|
82
88
|
// Resolve the deployment block number.
|
|
83
89
|
const deploymentBlock = spokePool.deploymentBlock;
|
|
84
90
|
|
|
@@ -109,13 +115,13 @@ export async function getBlockRangeForDepositId(
|
|
|
109
115
|
});
|
|
110
116
|
|
|
111
117
|
// Define a mapping of block numbers to number of deposits at that block. This saves repeated lookups.
|
|
112
|
-
const queriedIds: Record<number,
|
|
118
|
+
const queriedIds: Record<number, BigNumber> = {};
|
|
113
119
|
|
|
114
120
|
// Define a llambda function to get the deposit ID at a block number. This function will first check the
|
|
115
121
|
// queriedIds cache to see if the deposit ID at the block number has already been queried. If not, it will
|
|
116
122
|
// make an eth_call request to get the deposit ID at the block number. It will then cache the deposit ID
|
|
117
123
|
// in the queriedIds cache.
|
|
118
|
-
const _getDepositIdAtBlock = async (blockNumber: number): Promise<
|
|
124
|
+
const _getDepositIdAtBlock = async (blockNumber: number): Promise<BigNumber> => {
|
|
119
125
|
queriedIds[blockNumber] ??= await spokePool._getDepositIdAtBlock(blockNumber);
|
|
120
126
|
return queriedIds[blockNumber];
|
|
121
127
|
};
|
|
@@ -128,7 +134,7 @@ export async function getBlockRangeForDepositId(
|
|
|
128
134
|
|
|
129
135
|
// If the deposit ID at the initial high block is less than the target deposit ID, then we know that
|
|
130
136
|
// the target deposit ID must be greater than the initial high block, so we can throw an error.
|
|
131
|
-
if (highestDepositIdInRange
|
|
137
|
+
if (highestDepositIdInRange.lte(targetDepositId)) {
|
|
132
138
|
// initLow = 5: Deposits Num: 10
|
|
133
139
|
// // targetId = 11 <- fail (triggers this error) // 10 <= 11
|
|
134
140
|
// // targetId = 10 <- fail (triggers this error) // 10 <= 10
|
|
@@ -140,7 +146,7 @@ export async function getBlockRangeForDepositId(
|
|
|
140
146
|
|
|
141
147
|
// If the deposit ID at the initial low block is greater than the target deposit ID, then we know that
|
|
142
148
|
// the target deposit ID must be less than the initial low block, so we can throw an error.
|
|
143
|
-
if (lowestDepositIdInRange
|
|
149
|
+
if (lowestDepositIdInRange.gt(targetDepositId)) {
|
|
144
150
|
// initLow = 5: Deposits Num: 10
|
|
145
151
|
// initLow-1 = 4: Deposits Num: 2
|
|
146
152
|
// // targetId = 1 <- fail (triggers this error)
|
|
@@ -154,7 +160,6 @@ export async function getBlockRangeForDepositId(
|
|
|
154
160
|
// Define the low and high block numbers for the binary search.
|
|
155
161
|
let low = initLow;
|
|
156
162
|
let high = initHigh;
|
|
157
|
-
|
|
158
163
|
// Define the number of searches performed so far.
|
|
159
164
|
let searches = 0;
|
|
160
165
|
|
|
@@ -166,12 +171,12 @@ export async function getBlockRangeForDepositId(
|
|
|
166
171
|
const midDepositId = await _getDepositIdAtBlock(mid);
|
|
167
172
|
|
|
168
173
|
// Let's define the latest ID of the current midpoint block.
|
|
169
|
-
const accountedIdByMidBlock = midDepositId
|
|
174
|
+
const accountedIdByMidBlock = midDepositId.sub(bnOne);
|
|
170
175
|
|
|
171
176
|
// If our target deposit ID is less than the smallest range of our
|
|
172
177
|
// midpoint deposit ID range, then we know that the target deposit ID
|
|
173
178
|
// must be in the lower half of the block range.
|
|
174
|
-
if (targetDepositId
|
|
179
|
+
if (targetDepositId.lte(accountedIdByMidBlock)) {
|
|
175
180
|
high = mid;
|
|
176
181
|
}
|
|
177
182
|
// If our target deposit ID is greater than the largest range of our
|
|
@@ -200,10 +205,11 @@ export async function getBlockRangeForDepositId(
|
|
|
200
205
|
* @param blockTag The block number to search for the deposit ID at.
|
|
201
206
|
* @returns The deposit ID.
|
|
202
207
|
*/
|
|
203
|
-
export async function getDepositIdAtBlock(contract: Contract, blockTag: number): Promise<
|
|
204
|
-
const
|
|
208
|
+
export async function getDepositIdAtBlock(contract: Contract, blockTag: number): Promise<BigNumber> {
|
|
209
|
+
const _depositIdAtBlock = await contract.numberOfDeposits({ blockTag });
|
|
210
|
+
const depositIdAtBlock = toBN(_depositIdAtBlock);
|
|
205
211
|
// Sanity check to ensure that the deposit ID is an integer and is greater than or equal to zero.
|
|
206
|
-
if (
|
|
212
|
+
if (depositIdAtBlock.lt(bnZero)) {
|
|
207
213
|
throw new Error("Invalid deposit count");
|
|
208
214
|
}
|
|
209
215
|
return depositIdAtBlock;
|
|
@@ -244,7 +250,7 @@ export function getRelayHashFromEvent(e: Deposit | Fill | SlowFillRequest): stri
|
|
|
244
250
|
return getRelayDataHash(e, e.destinationChainId);
|
|
245
251
|
}
|
|
246
252
|
|
|
247
|
-
export function isUnsafeDepositId(depositId:
|
|
253
|
+
export function isUnsafeDepositId(depositId: BigNumber): boolean {
|
|
248
254
|
// SpokePool.unsafeDepositV3() produces a uint256 depositId by hashing the msg.sender, depositor and input
|
|
249
255
|
// uint256 depositNonce. There is a possibility that this resultant uint256 is less than the maxSafeDepositId (i.e.
|
|
250
256
|
// the maximum uint32 value) which makes it possible that an unsafeDepositV3's depositId can collide with a safe
|
|
@@ -380,3 +386,8 @@ export async function findFillBlock(
|
|
|
380
386
|
|
|
381
387
|
return lowBlockNumber;
|
|
382
388
|
}
|
|
389
|
+
|
|
390
|
+
// Determines if the input address (either a bytes32 or bytes20) is the zero address.
|
|
391
|
+
export function isZeroAddress(address: string): boolean {
|
|
392
|
+
return address === ZERO_ADDRESS || address === ZERO_BYTES;
|
|
393
|
+
}
|
|
@@ -8,7 +8,7 @@ const HexValidator = define<string>("HexValidator", (v) => ethersUtils.isHexStri
|
|
|
8
8
|
const BigNumberValidator = define<BigNumber>("BigNumberValidator", (v) => BigNumber.isBigNumber(v));
|
|
9
9
|
|
|
10
10
|
const V3DepositSchema = object({
|
|
11
|
-
depositId:
|
|
11
|
+
depositId: BigNumberValidator,
|
|
12
12
|
depositor: AddressValidator,
|
|
13
13
|
recipient: AddressValidator,
|
|
14
14
|
inputToken: AddressValidator,
|