@across-protocol/sdk 4.0.0-beta.9 → 4.0.1

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.
Files changed (132) hide show
  1. package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +5 -4
  2. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +345 -187
  3. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  4. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.d.ts +1 -2
  5. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +1 -2
  6. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  7. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +5 -1
  8. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +47 -1
  9. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  10. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
  11. package/dist/cjs/clients/SpokePoolClient.d.ts +1 -0
  12. package/dist/cjs/clients/SpokePoolClient.js +10 -1
  13. package/dist/cjs/clients/SpokePoolClient.js.map +1 -1
  14. package/dist/cjs/clients/mocks/MockSpokePoolClient.d.ts +2 -1
  15. package/dist/cjs/clients/mocks/MockSpokePoolClient.js +11 -0
  16. package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
  17. package/dist/cjs/constants.d.ts +0 -1
  18. package/dist/cjs/constants.js +1 -2
  19. package/dist/cjs/constants.js.map +1 -1
  20. package/dist/cjs/providers/index.d.ts +1 -0
  21. package/dist/cjs/providers/index.js +2 -0
  22. package/dist/cjs/providers/index.js.map +1 -1
  23. package/dist/cjs/providers/mockProvider.d.ts +19 -0
  24. package/dist/cjs/providers/mockProvider.js +70 -0
  25. package/dist/cjs/providers/mockProvider.js.map +1 -0
  26. package/dist/cjs/utils/AddressUtils.d.ts +1 -0
  27. package/dist/cjs/utils/AddressUtils.js +6 -1
  28. package/dist/cjs/utils/AddressUtils.js.map +1 -1
  29. package/dist/cjs/utils/BlockUtils.js +1 -0
  30. package/dist/cjs/utils/BlockUtils.js.map +1 -1
  31. package/dist/cjs/utils/DepositUtils.js +1 -1
  32. package/dist/cjs/utils/DepositUtils.js.map +1 -1
  33. package/dist/cjs/utils/EventUtils.js +21 -0
  34. package/dist/cjs/utils/EventUtils.js.map +1 -1
  35. package/dist/cjs/utils/NetworkUtils.js +2 -1
  36. package/dist/cjs/utils/NetworkUtils.js.map +1 -1
  37. package/dist/cjs/utils/SpokeUtils.d.ts +1 -0
  38. package/dist/cjs/utils/SpokeUtils.js +15 -8
  39. package/dist/cjs/utils/SpokeUtils.js.map +1 -1
  40. package/dist/cjs/utils/common.d.ts +1 -0
  41. package/dist/cjs/utils/common.js +2 -1
  42. package/dist/cjs/utils/common.js.map +1 -1
  43. package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +5 -4
  44. package/dist/esm/clients/BundleDataClient/BundleDataClient.js +448 -281
  45. package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  46. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.d.ts +1 -2
  47. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +2 -3
  48. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  49. package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +5 -1
  50. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +54 -1
  51. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  52. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
  53. package/dist/esm/clients/SpokePoolClient.d.ts +8 -0
  54. package/dist/esm/clients/SpokePoolClient.js +17 -1
  55. package/dist/esm/clients/SpokePoolClient.js.map +1 -1
  56. package/dist/esm/clients/mocks/MockSpokePoolClient.d.ts +2 -1
  57. package/dist/esm/clients/mocks/MockSpokePoolClient.js +11 -0
  58. package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
  59. package/dist/esm/constants.d.ts +0 -1
  60. package/dist/esm/constants.js +0 -1
  61. package/dist/esm/constants.js.map +1 -1
  62. package/dist/esm/providers/index.d.ts +1 -0
  63. package/dist/esm/providers/index.js +2 -0
  64. package/dist/esm/providers/index.js.map +1 -1
  65. package/dist/esm/providers/mockProvider.d.ts +23 -0
  66. package/dist/esm/providers/mockProvider.js +73 -0
  67. package/dist/esm/providers/mockProvider.js.map +1 -0
  68. package/dist/esm/utils/AddressUtils.d.ts +1 -0
  69. package/dist/esm/utils/AddressUtils.js +9 -0
  70. package/dist/esm/utils/AddressUtils.js.map +1 -1
  71. package/dist/esm/utils/BlockUtils.js +1 -0
  72. package/dist/esm/utils/BlockUtils.js.map +1 -1
  73. package/dist/esm/utils/DepositUtils.js +2 -2
  74. package/dist/esm/utils/DepositUtils.js.map +1 -1
  75. package/dist/esm/utils/EventUtils.js +29 -1
  76. package/dist/esm/utils/EventUtils.js.map +1 -1
  77. package/dist/esm/utils/NetworkUtils.js +2 -1
  78. package/dist/esm/utils/NetworkUtils.js.map +1 -1
  79. package/dist/esm/utils/SpokeUtils.d.ts +1 -0
  80. package/dist/esm/utils/SpokeUtils.js +13 -7
  81. package/dist/esm/utils/SpokeUtils.js.map +1 -1
  82. package/dist/esm/utils/abi/typechain/Multicall3.d.ts +4 -1
  83. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -1
  84. package/dist/esm/utils/common.d.ts +1 -0
  85. package/dist/esm/utils/common.js +1 -0
  86. package/dist/esm/utils/common.js.map +1 -1
  87. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +5 -4
  88. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
  89. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts +1 -2
  90. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -1
  91. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +5 -1
  92. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
  93. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +4 -4
  94. package/dist/types/clients/SpokePoolClient.d.ts +8 -0
  95. package/dist/types/clients/SpokePoolClient.d.ts.map +1 -1
  96. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts +2 -1
  97. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts.map +1 -1
  98. package/dist/types/constants.d.ts +0 -1
  99. package/dist/types/constants.d.ts.map +1 -1
  100. package/dist/types/providers/index.d.ts +1 -0
  101. package/dist/types/providers/index.d.ts.map +1 -1
  102. package/dist/types/providers/mockProvider.d.ts +24 -0
  103. package/dist/types/providers/mockProvider.d.ts.map +1 -0
  104. package/dist/types/utils/AddressUtils.d.ts +1 -0
  105. package/dist/types/utils/AddressUtils.d.ts.map +1 -1
  106. package/dist/types/utils/BlockUtils.d.ts.map +1 -1
  107. package/dist/types/utils/EventUtils.d.ts.map +1 -1
  108. package/dist/types/utils/NetworkUtils.d.ts.map +1 -1
  109. package/dist/types/utils/SpokeUtils.d.ts +1 -0
  110. package/dist/types/utils/SpokeUtils.d.ts.map +1 -1
  111. package/dist/types/utils/abi/typechain/Multicall3.d.ts +4 -1
  112. package/dist/types/utils/abi/typechain/Multicall3.d.ts.map +1 -1
  113. package/dist/types/utils/abi/typechain/common.d.ts.map +1 -1
  114. package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts.map +1 -1
  115. package/dist/types/utils/common.d.ts +1 -0
  116. package/dist/types/utils/common.d.ts.map +1 -1
  117. package/package.json +3 -3
  118. package/src/clients/BundleDataClient/BundleDataClient.ts +406 -249
  119. package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +0 -8
  120. package/src/clients/BundleDataClient/utils/FillUtils.ts +66 -2
  121. package/src/clients/SpokePoolClient.ts +16 -3
  122. package/src/clients/mocks/MockSpokePoolClient.ts +14 -0
  123. package/src/constants.ts +0 -2
  124. package/src/providers/index.ts +1 -0
  125. package/src/providers/mockProvider.ts +77 -0
  126. package/src/utils/AddressUtils.ts +10 -0
  127. package/src/utils/BlockUtils.ts +1 -0
  128. package/src/utils/DepositUtils.ts +2 -2
  129. package/src/utils/EventUtils.ts +29 -1
  130. package/src/utils/NetworkUtils.ts +2 -1
  131. package/src/utils/SpokeUtils.ts +21 -8
  132. package/src/utils/common.ts +2 -0
@@ -14,7 +14,6 @@ import {
14
14
  import {
15
15
  bnZero,
16
16
  AnyObject,
17
- groupObjectCountsByTwoProps,
18
17
  fixedPointAdjustment,
19
18
  count2DDictionaryValues,
20
19
  count3DDictionaryValues,
@@ -26,7 +25,6 @@ import {
26
25
  updateRunningBalance,
27
26
  updateRunningBalanceForDeposit,
28
27
  } from "./PoolRebalanceUtils";
29
- import { V3FillWithBlock } from "./shims";
30
28
  import { AcrossConfigStoreClient } from "../../AcrossConfigStoreClient";
31
29
  import { HubPoolClient } from "../../HubPoolClient";
32
30
  import { buildPoolRebalanceLeafTree } from "./MerkleTreeUtils";
@@ -83,7 +81,6 @@ export function getRefundsFromBundle(
83
81
  export function prettyPrintV3SpokePoolEvents(
84
82
  bundleDepositsV3: BundleDepositsV3,
85
83
  bundleFillsV3: BundleFillsV3,
86
- bundleInvalidFillsV3: V3FillWithBlock[],
87
84
  bundleSlowFillsV3: BundleSlowFills,
88
85
  expiredDepositsToRefundV3: ExpiredDepositsToRefundV3,
89
86
  unexecutableSlowFills: BundleExcessSlowFills
@@ -94,11 +91,6 @@ export function prettyPrintV3SpokePoolEvents(
94
91
  bundleSlowFillsV3: count2DDictionaryValues(bundleSlowFillsV3),
95
92
  expiredDepositsToRefundV3: count2DDictionaryValues(expiredDepositsToRefundV3),
96
93
  unexecutableSlowFills: count2DDictionaryValues(unexecutableSlowFills),
97
- allInvalidFillsInRangeByDestinationChainAndRelayer: groupObjectCountsByTwoProps(
98
- bundleInvalidFillsV3,
99
- "destinationChainId",
100
- (fill) => `${fill.relayer}`
101
- ),
102
94
  };
103
95
  }
104
96
 
@@ -1,5 +1,7 @@
1
- import { Fill } from "../../../interfaces";
2
- import { getBlockRangeForChain, isSlowFill } from "../../../utils";
1
+ import _ from "lodash";
2
+ import { providers } from "ethers";
3
+ import { Deposit, DepositWithBlock, Fill, FillWithBlock } from "../../../interfaces";
4
+ import { getBlockRangeForChain, isSlowFill, chainIsEvm, isValidEvmAddress, isDefined } from "../../../utils";
3
5
  import { HubPoolClient } from "../../HubPoolClient";
4
6
 
5
7
  export function getRefundInformationFromFill(
@@ -44,3 +46,65 @@ export function getRefundInformationFromFill(
44
46
  repaymentToken,
45
47
  };
46
48
  }
49
+
50
+ export function getRepaymentChainId(fill: Fill, matchedDeposit: Deposit): number {
51
+ // Lite chain deposits force repayment on origin chain.
52
+ return matchedDeposit.fromLiteChain ? fill.originChainId : fill.repaymentChainId;
53
+ }
54
+
55
+ export function isEvmRepaymentValid(
56
+ fill: Fill,
57
+ repaymentChainId: number,
58
+ possibleRepaymentChainIds: number[] = []
59
+ ): boolean {
60
+ // Slow fills don't result in repayments so they're always valid.
61
+ if (isSlowFill(fill)) {
62
+ return true;
63
+ }
64
+ // Return undefined if the requested repayment chain ID is not in a passed in set of eligible chains. This can
65
+ // be used by the caller to narrow the chains to those that are not disabled in the config store.
66
+ if (possibleRepaymentChainIds.length > 0 && !possibleRepaymentChainIds.includes(repaymentChainId)) {
67
+ return false;
68
+ }
69
+ return chainIsEvm(repaymentChainId) && isValidEvmAddress(fill.relayer);
70
+ }
71
+
72
+ // Verify that a fill sent to an EVM chain has a 20 byte address. If the fill does not, then attempt
73
+ // to repay the `msg.sender` of the relay transaction. Otherwise, return undefined.
74
+ export async function verifyFillRepayment(
75
+ _fill: FillWithBlock,
76
+ destinationChainProvider: providers.Provider,
77
+ matchedDeposit: DepositWithBlock,
78
+ possibleRepaymentChainIds: number[] = []
79
+ ): Promise<FillWithBlock | undefined> {
80
+ const fill = _.cloneDeep(_fill);
81
+
82
+ const repaymentChainId = getRepaymentChainId(fill, matchedDeposit);
83
+ const validEvmRepayment = isEvmRepaymentValid(fill, repaymentChainId, possibleRepaymentChainIds);
84
+
85
+ // Case 1: Repayment chain is EVM and repayment address is valid EVM address.
86
+ if (validEvmRepayment) {
87
+ return fill;
88
+ }
89
+ // Case 2: Repayment chain is EVM but repayment address is not a valid EVM address. Attempt to switch repayment
90
+ // address to msg.sender of relay transaction.
91
+ else if (chainIsEvm(repaymentChainId) && !isValidEvmAddress(fill.relayer)) {
92
+ // TODO: Handle case where fill was sent on non-EVM chain, in which case the following call would fail
93
+ // or return something unexpected. We'd want to return undefined here.
94
+ const fillTransaction = await destinationChainProvider.getTransaction(fill.transactionHash);
95
+ const destinationRelayer = fillTransaction?.from;
96
+ // Repayment chain is still an EVM chain, but the msg.sender is a bytes32 address, so the fill is invalid.
97
+ if (!isDefined(destinationRelayer) || !isValidEvmAddress(destinationRelayer)) {
98
+ return undefined;
99
+ }
100
+ // Otherwise, assume the relayer to be repaid is the msg.sender. We don't need to modify the repayment chain since
101
+ // the getTransaction() call would only succeed if the fill was sent on an EVM chain and therefore the msg.sender
102
+ // is a valid EVM address and the repayment chain is an EVM chain.
103
+ fill.relayer = destinationRelayer;
104
+ return fill;
105
+ }
106
+ // Case 3: Repayment chain is not an EVM chain, must be invalid.
107
+ else {
108
+ return undefined;
109
+ }
110
+ }
@@ -135,6 +135,18 @@ export class SpokePoolClient extends BaseAbstractClient {
135
135
  return Object.values(this.depositHashes).filter((deposit) => deposit.destinationChainId === destinationChainId);
136
136
  }
137
137
 
138
+ /**
139
+ * Retrieves a list of duplicate deposits matching the given deposit's deposit hash.
140
+ * @notice A duplicate is considered any deposit sent after the original deposit with the same deposit hash.
141
+ * @param deposit The deposit to find duplicates for.
142
+ * @returns A list of duplicate deposits. Does NOT include the original deposit
143
+ * unless the original deposit is a duplicate.
144
+ */
145
+ private _getDuplicateDeposits(deposit: DepositWithBlock): DepositWithBlock[] {
146
+ const depositHash = this.getDepositHash(deposit);
147
+ return this.duplicateDepositHashes[depositHash] ?? [];
148
+ }
149
+
138
150
  /**
139
151
  * Returns a list of all deposits including any duplicate ones. Designed only to be used in use cases where
140
152
  * all deposits are required, regardless of duplicates. For example, the Dataworker can use this to refund
@@ -144,9 +156,10 @@ export class SpokePoolClient extends BaseAbstractClient {
144
156
  */
145
157
  public getDepositsForDestinationChainWithDuplicates(destinationChainId: number): DepositWithBlock[] {
146
158
  const deposits = this.getDepositsForDestinationChain(destinationChainId);
147
- const duplicateDeposits = Object.values(this.duplicateDepositHashes).filter(
148
- (deposits) => deposits.length > 0 && deposits[0].destinationChainId === destinationChainId
149
- );
159
+ const duplicateDeposits = deposits.reduce((acc, deposit) => {
160
+ const duplicates = this._getDuplicateDeposits(deposit);
161
+ return acc.concat(duplicates);
162
+ }, [] as DepositWithBlock[]);
150
163
  return sortEventsAscendingInPlace(deposits.concat(duplicateDeposits.flat()));
151
164
  }
152
165
 
@@ -13,6 +13,7 @@ import {
13
13
  FillWithBlock,
14
14
  SlowFillLeaf,
15
15
  SpeedUp,
16
+ TokensBridged,
16
17
  } from "../../interfaces";
17
18
  import { toBN, toBNWei, getCurrentTime, randomAddress, BigNumber, bnZero, bnOne, bnMax } from "../../utils";
18
19
  import { SpokePoolClient, SpokePoolUpdate } from "../SpokePoolClient";
@@ -224,6 +225,19 @@ export class MockSpokePoolClient extends SpokePoolClient {
224
225
  });
225
226
  }
226
227
 
228
+ setTokensBridged(tokensBridged: TokensBridged): Log {
229
+ const event = "TokensBridged";
230
+ const topics = [tokensBridged.chainId, tokensBridged.leafId, tokensBridged.l2TokenAddress];
231
+ const args = { ...tokensBridged };
232
+
233
+ return this.eventManager.generateEvent({
234
+ event,
235
+ address: this.spokePool.address,
236
+ topics: topics.map((topic) => topic.toString()),
237
+ args,
238
+ });
239
+ }
240
+
227
241
  requestV3SlowFill(request: SlowFillRequestWithBlock): Log {
228
242
  const event = "RequestedV3SlowFill";
229
243
 
package/src/constants.ts CHANGED
@@ -57,8 +57,6 @@ export const DEFAULT_ARWEAVE_STORAGE_ADDRESS = "Z6hjBM8FHu90lYWB8o5jR1dfX92FlV2W
57
57
 
58
58
  export const EMPTY_MESSAGE = "0x";
59
59
 
60
- export const EMPTY_MESSAGE_HASH = ethersConstants.HashZero;
61
-
62
60
  export const BRIDGED_USDC_SYMBOLS = [
63
61
  TOKEN_SYMBOLS_MAP["USDC.e"].symbol,
64
62
  TOKEN_SYMBOLS_MAP.USDbC.symbol,
@@ -5,3 +5,4 @@ export * from "./speedProvider";
5
5
  export * from "./constants";
6
6
  export * from "./types";
7
7
  export * from "./utils";
8
+ export * as mocks from "./mockProvider";
@@ -0,0 +1,77 @@
1
+ import { BigNumber, providers } from "ethers";
2
+ import { Block, BlockTag, FeeData, TransactionResponse } from "@ethersproject/abstract-provider";
3
+ import { bnZero } from "../utils/BigNumberUtils";
4
+
5
+ /**
6
+ * @notice Class used to test GasPriceOracle which makes ethers provider calls to the following implemented
7
+ * methods.
8
+ */
9
+ export class MockedProvider extends providers.StaticJsonRpcProvider {
10
+ private transactions: { [hash: string]: TransactionResponse } = {};
11
+
12
+ constructor(
13
+ readonly stdLastBaseFeePerGas: BigNumber,
14
+ readonly stdMaxPriorityFeePerGas: BigNumber,
15
+ readonly defaultChainId = 1
16
+ ) {
17
+ super(undefined, defaultChainId);
18
+ }
19
+
20
+ getBlock(_blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<Block> {
21
+ const mockBlock: Block = {
22
+ transactions: [],
23
+ hash: "0x",
24
+ parentHash: "0x",
25
+ number: 0,
26
+ nonce: "0",
27
+ difficulty: 0,
28
+ _difficulty: bnZero,
29
+ timestamp: 0,
30
+ gasLimit: bnZero,
31
+ gasUsed: bnZero,
32
+ baseFeePerGas: this.stdLastBaseFeePerGas,
33
+ miner: "0x",
34
+ extraData: "0x",
35
+ };
36
+ return Promise.resolve(mockBlock);
37
+ }
38
+
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ send(method: string, _params: Array<any>): Promise<any> {
41
+ switch (method) {
42
+ case "eth_maxPriorityFeePerGas":
43
+ return Promise.resolve(this.stdMaxPriorityFeePerGas);
44
+ default:
45
+ throw new Error(`MockedProvider#Unimplemented method: ${method}`);
46
+ }
47
+ }
48
+
49
+ getFeeData(): Promise<FeeData> {
50
+ return Promise.resolve({
51
+ lastBaseFeePerGas: this.stdLastBaseFeePerGas,
52
+ maxPriorityFeePerGas: this.stdMaxPriorityFeePerGas,
53
+ // Following fields unused in GasPrice oracle
54
+ maxFeePerGas: null,
55
+ gasPrice: null,
56
+ });
57
+ }
58
+
59
+ getTransaction(hash: string): Promise<TransactionResponse> {
60
+ return Promise.resolve(this.transactions[hash]);
61
+ }
62
+
63
+ getGasPrice(): Promise<BigNumber> {
64
+ return Promise.resolve(this.stdLastBaseFeePerGas.add(this.stdMaxPriorityFeePerGas));
65
+ }
66
+
67
+ getNetwork(): Promise<{ chainId: number; name: string }> {
68
+ return Promise.resolve({
69
+ name: "mocknetwork",
70
+ chainId: this.defaultChainId,
71
+ });
72
+ }
73
+
74
+ _setTransaction(hash: string, transaction: TransactionResponse) {
75
+ this.transactions[hash] = transaction;
76
+ }
77
+ }
@@ -39,6 +39,16 @@ export function compareAddressesSimple(addressA?: string, addressB?: string): bo
39
39
  return addressA.toLowerCase() === addressB.toLowerCase();
40
40
  }
41
41
 
42
+ // Converts an input (assumed to be) bytes32 string into a bytes20 string.
43
+ // If the input is not a bytes32 but is less than type(uint160).max, then this function
44
+ // will still succeed.
45
+ // Throws an error if the string as an unsigned integer is greater than type(uint160).max.
46
+ export function toAddress(hexString: string): string {
47
+ // rawAddress is the address which is not properly checksummed.
48
+ const rawAddress = utils.hexZeroPad(utils.hexStripZeros(hexString), 20);
49
+ return utils.getAddress(rawAddress);
50
+ }
51
+
42
52
  export function isValidEvmAddress(address: string): boolean {
43
53
  if (utils.isAddress(address)) {
44
54
  return true;
@@ -34,6 +34,7 @@ const defaultHighBlockOffset = 10;
34
34
  const cacheTTL = 60 * 15;
35
35
  const now = getCurrentTime(); // Seed the cache with initial values.
36
36
  const blockTimes: { [chainId: number]: BlockTimeAverage } = {
37
+ [CHAIN_IDs.DOCTOR_WHO]: { average: 1, timestamp: now, blockRange: 1 },
37
38
  [CHAIN_IDs.INK]: { average: 1, timestamp: now, blockRange: 1 },
38
39
  [CHAIN_IDs.LINEA]: { average: 3, timestamp: now, blockRange: 1 },
39
40
  [CHAIN_IDs.MAINNET]: { average: 12.5, timestamp: now, blockRange: 1 },
@@ -1,6 +1,6 @@
1
1
  import assert from "assert";
2
2
  import { SpokePoolClient } from "../clients";
3
- import { DEFAULT_CACHING_TTL, EMPTY_MESSAGE, EMPTY_MESSAGE_HASH } from "../constants";
3
+ import { DEFAULT_CACHING_TTL, EMPTY_MESSAGE, ZERO_BYTES } from "../constants";
4
4
  import { CachingMechanismInterface, Deposit, DepositWithBlock, Fill, SlowFillRequest } from "../interfaces";
5
5
  import { getNetworkName } from "./NetworkUtils";
6
6
  import { getDepositInCache, getDepositKey, setDepositInCache } from "./CachingUtils";
@@ -160,7 +160,7 @@ export function isMessageEmpty(message = EMPTY_MESSAGE): boolean {
160
160
  }
161
161
 
162
162
  export function isFillOrSlowFillRequestMessageEmpty(message: string): boolean {
163
- return isMessageEmpty(message) || message === EMPTY_MESSAGE_HASH;
163
+ return isMessageEmpty(message) || message === ZERO_BYTES;
164
164
  }
165
165
 
166
166
  /**
@@ -3,11 +3,27 @@ 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
+ import { isDefined, toBN, BigNumberish, toAddress } from "./";
7
7
 
8
8
  const maxRetries = 3;
9
9
  const retrySleepTime = 10;
10
10
 
11
+ // Event fields which changed from an `address` to `bytes32` after the SVM contract upgrade.
12
+ const knownExtendedAddressFields = [
13
+ // TokensBridged
14
+ "l2TokenAddress",
15
+ // FundsDeposited/FilledRelay/RequestedSlowFill
16
+ "inputToken",
17
+ "outputToken",
18
+ "depositor",
19
+ "recipient",
20
+ "exclusiveRelayer",
21
+ // FilledRelay
22
+ "relayer",
23
+ // RequestedSpeedUpDeposit
24
+ "updatedRecipient",
25
+ ];
26
+
11
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
28
  export function spreadEvent(args: Result | Record<string, unknown>): { [key: string]: any } {
13
29
  const keys = Object.keys(args).filter((key: string) => isNaN(+key)); // Extract non-numeric keys.
@@ -67,6 +83,18 @@ export function spreadEvent(args: Result | Record<string, unknown>): { [key: str
67
83
  returnedObject.depositId = toBN(returnedObject.depositId as BigNumberish);
68
84
  }
69
85
 
86
+ // Truncate all fields which may be bytes32 into a bytes20 string.
87
+ for (const field of knownExtendedAddressFields) {
88
+ if (isDefined(returnedObject[field])) {
89
+ let address = String(returnedObject[field]);
90
+ try {
91
+ address = toAddress(address);
92
+ // eslint-disable-next-line no-empty
93
+ } catch (_) {}
94
+ returnedObject[field] = address;
95
+ }
96
+ }
97
+
70
98
  return returnedObject;
71
99
  }
72
100
 
@@ -142,9 +142,10 @@ export function chainIsEvm(chainId: number): boolean {
142
142
  export function chainIsCCTPEnabled(chainId: number): boolean {
143
143
  return [
144
144
  // Mainnets
145
+ CHAIN_IDs.ARBITRUM,
145
146
  CHAIN_IDs.BASE,
147
+ CHAIN_IDs.DOCTOR_WHO,
146
148
  CHAIN_IDs.OPTIMISM,
147
- CHAIN_IDs.ARBITRUM,
148
149
  CHAIN_IDs.POLYGON,
149
150
  // Testnets
150
151
  CHAIN_IDs.BASE_SEPOLIA,
@@ -5,6 +5,8 @@ import { Deposit, Fill, FillStatus, FillWithBlock, RelayData, SlowFillRequest }
5
5
  import { SpokePoolClient } from "../clients";
6
6
  import { chunk } from "./ArrayUtils";
7
7
  import { BigNumber, toBN, bnOne, bnZero } from "./BigNumberUtils";
8
+ import { keccak256 } from "./common";
9
+ import { isMessageEmpty } from "./DepositUtils";
8
10
  import { isDefined } from "./TypeGuards";
9
11
  import { getNetworkName } from "./NetworkUtils";
10
12
  import { paginatedEventQuery, spreadEventWithBlockNumber } from "./EventUtils";
@@ -223,26 +225,34 @@ export async function getDepositIdAtBlock(contract: Contract, blockTag: number):
223
225
  * @returns The corresponding RelayData hash.
224
226
  */
225
227
  export function getRelayDataHash(relayData: RelayData, destinationChainId: number): string {
228
+ const _relayData = {
229
+ ...relayData,
230
+ depositor: ethersUtils.hexZeroPad(relayData.depositor, 32),
231
+ recipient: ethersUtils.hexZeroPad(relayData.recipient, 32),
232
+ inputToken: ethersUtils.hexZeroPad(relayData.inputToken, 32),
233
+ outputToken: ethersUtils.hexZeroPad(relayData.outputToken, 32),
234
+ exclusiveRelayer: ethersUtils.hexZeroPad(relayData.exclusiveRelayer, 32),
235
+ };
226
236
  return ethersUtils.keccak256(
227
237
  ethersUtils.defaultAbiCoder.encode(
228
238
  [
229
239
  "tuple(" +
230
- "address depositor," +
231
- "address recipient," +
232
- "address exclusiveRelayer," +
233
- "address inputToken," +
234
- "address outputToken," +
240
+ "bytes32 depositor," +
241
+ "bytes32 recipient," +
242
+ "bytes32 exclusiveRelayer," +
243
+ "bytes32 inputToken," +
244
+ "bytes32 outputToken," +
235
245
  "uint256 inputAmount," +
236
246
  "uint256 outputAmount," +
237
247
  "uint256 originChainId," +
238
- "uint32 depositId," +
248
+ "uint256 depositId," +
239
249
  "uint32 fillDeadline," +
240
250
  "uint32 exclusivityDeadline," +
241
251
  "bytes message" +
242
252
  ")",
243
253
  "uint256 destinationChainId",
244
254
  ],
245
- [relayData, destinationChainId]
255
+ [_relayData, destinationChainId]
246
256
  )
247
257
  );
248
258
  }
@@ -412,7 +422,6 @@ export async function findFillEvent(
412
422
  // In production the chainId returned from the provider matches 1:1 with the actual chainId. Querying the provider
413
423
  // object saves an RPC query becasue the chainId is cached by StaticJsonRpcProvider instances. In hre, the SpokePool
414
424
  // may be configured with a different chainId than what is returned by the provider.
415
- // @todo Sub out actual chain IDs w/ CHAIN_IDs constants
416
425
  const destinationChainId = Object.values(CHAIN_IDs).includes(relayData.originChainId)
417
426
  ? (await spokePool.provider.getNetwork()).chainId
418
427
  : Number(await spokePool.chainId());
@@ -427,3 +436,7 @@ export async function findFillEvent(
427
436
  export function isZeroAddress(address: string): boolean {
428
437
  return address === ZERO_ADDRESS || address === ZERO_BYTES;
429
438
  }
439
+
440
+ export function getMessageHash(message: string): string {
441
+ return isMessageEmpty(message) ? ZERO_BYTES : keccak256(message);
442
+ }
@@ -7,6 +7,8 @@ export type Decimalish = string | number | Decimal;
7
7
  export const AddressZero = ethers.constants.AddressZero;
8
8
  export const MAX_BIG_INT = BigNumber.from(Number.MAX_SAFE_INTEGER.toString());
9
9
 
10
+ export const { keccak256 } = ethers.utils;
11
+
10
12
  /**
11
13
  * toBNWei.
12
14
  *