@across-protocol/sdk 4.3.62 → 4.3.63

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 (79) hide show
  1. package/dist/cjs/constants.d.ts +2 -0
  2. package/dist/cjs/constants.js +2 -0
  3. package/dist/cjs/constants.js.map +1 -1
  4. package/dist/cjs/gasPriceOracle/oracle.js +1 -0
  5. package/dist/cjs/gasPriceOracle/oracle.js.map +1 -1
  6. package/dist/cjs/gasPriceOracle/types.d.ts +2 -0
  7. package/dist/cjs/gasPriceOracle/types.js +8 -0
  8. package/dist/cjs/gasPriceOracle/types.js.map +1 -1
  9. package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.d.ts +1 -0
  10. package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js +3 -0
  11. package/dist/cjs/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
  12. package/dist/cjs/relayFeeCalculator/chain-queries/factory.d.ts +28 -0
  13. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.d.ts +1 -0
  14. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js +3 -0
  15. package/dist/cjs/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  16. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.d.ts +52 -8
  17. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js +104 -41
  18. package/dist/cjs/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
  19. package/dist/cjs/utils/FormattingUtils.js +1 -1
  20. package/dist/cjs/utils/FormattingUtils.js.map +1 -1
  21. package/dist/cjs/utils/Multicall.js +2 -0
  22. package/dist/cjs/utils/Multicall.js.map +1 -1
  23. package/dist/cjs/utils/NetworkUtils.js +1 -1
  24. package/dist/cjs/utils/NetworkUtils.js.map +1 -1
  25. package/dist/cjs/utils/TokenUtils.d.ts +56 -0
  26. package/dist/esm/constants.d.ts +2 -0
  27. package/dist/esm/constants.js +2 -0
  28. package/dist/esm/constants.js.map +1 -1
  29. package/dist/esm/gasPriceOracle/oracle.js +1 -0
  30. package/dist/esm/gasPriceOracle/oracle.js.map +1 -1
  31. package/dist/esm/gasPriceOracle/types.d.ts +2 -0
  32. package/dist/esm/gasPriceOracle/types.js +7 -1
  33. package/dist/esm/gasPriceOracle/types.js.map +1 -1
  34. package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.d.ts +7 -0
  35. package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js +9 -0
  36. package/dist/esm/relayFeeCalculator/chain-queries/baseQuery.js.map +1 -1
  37. package/dist/esm/relayFeeCalculator/chain-queries/factory.d.ts +28 -0
  38. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.d.ts +8 -0
  39. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js +15 -2
  40. package/dist/esm/relayFeeCalculator/chain-queries/svmQuery.js.map +1 -1
  41. package/dist/esm/relayFeeCalculator/relayFeeCalculator.d.ts +81 -33
  42. package/dist/esm/relayFeeCalculator/relayFeeCalculator.js +112 -41
  43. package/dist/esm/relayFeeCalculator/relayFeeCalculator.js.map +1 -1
  44. package/dist/esm/utils/FormattingUtils.d.ts +1 -1
  45. package/dist/esm/utils/FormattingUtils.js +2 -2
  46. package/dist/esm/utils/FormattingUtils.js.map +1 -1
  47. package/dist/esm/utils/Multicall.js +2 -0
  48. package/dist/esm/utils/Multicall.js.map +1 -1
  49. package/dist/esm/utils/NetworkUtils.js +1 -1
  50. package/dist/esm/utils/NetworkUtils.js.map +1 -1
  51. package/dist/esm/utils/TokenUtils.d.ts +56 -0
  52. package/dist/types/constants.d.ts +2 -0
  53. package/dist/types/constants.d.ts.map +1 -1
  54. package/dist/types/gasPriceOracle/oracle.d.ts.map +1 -1
  55. package/dist/types/gasPriceOracle/types.d.ts +2 -0
  56. package/dist/types/gasPriceOracle/types.d.ts.map +1 -1
  57. package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts +7 -0
  58. package/dist/types/relayFeeCalculator/chain-queries/baseQuery.d.ts.map +1 -1
  59. package/dist/types/relayFeeCalculator/chain-queries/factory.d.ts +28 -0
  60. package/dist/types/relayFeeCalculator/chain-queries/factory.d.ts.map +1 -1
  61. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts +8 -0
  62. package/dist/types/relayFeeCalculator/chain-queries/svmQuery.d.ts.map +1 -1
  63. package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts +81 -33
  64. package/dist/types/relayFeeCalculator/relayFeeCalculator.d.ts.map +1 -1
  65. package/dist/types/utils/FormattingUtils.d.ts +1 -1
  66. package/dist/types/utils/FormattingUtils.d.ts.map +1 -1
  67. package/dist/types/utils/Multicall.d.ts.map +1 -1
  68. package/dist/types/utils/TokenUtils.d.ts +56 -0
  69. package/dist/types/utils/TokenUtils.d.ts.map +1 -1
  70. package/package.json +3 -3
  71. package/src/constants.ts +2 -0
  72. package/src/gasPriceOracle/oracle.ts +1 -0
  73. package/src/gasPriceOracle/types.ts +9 -1
  74. package/src/relayFeeCalculator/chain-queries/baseQuery.ts +10 -0
  75. package/src/relayFeeCalculator/chain-queries/svmQuery.ts +32 -2
  76. package/src/relayFeeCalculator/relayFeeCalculator.ts +111 -47
  77. package/src/utils/FormattingUtils.ts +2 -2
  78. package/src/utils/Multicall.ts +2 -0
  79. package/src/utils/NetworkUtils.ts +1 -1
@@ -160,6 +160,16 @@ export class QueryBase implements QueryInterface {
160
160
  return voidSigner.estimateGas(unsignedTx);
161
161
  }
162
162
 
163
+ /**
164
+ * @notice Return the native token cost of filling a deposit beyond gas cost. We're not using msg.value in our fills,
165
+ * so return zero for EVM side
166
+ * @param deposit RelayData associated with Deposit we're estimating for
167
+ * @returns Native token cost
168
+ */
169
+ getAuxiliaryNativeTokenCost(_deposit: RelayData): BigNumber {
170
+ return bnZero;
171
+ }
172
+
163
173
  /**
164
174
  * @notice Return L1 data fee for OP stack L2 transaction, which is based on L2 calldata.
165
175
  * @dev https://docs.optimism.io/stack/transactions/fees#l1-data-fee
@@ -5,12 +5,28 @@ import {
5
5
  fetchEncodedAccount,
6
6
  isSome,
7
7
  } from "@solana/kit";
8
- import { SVMProvider, SolanaVoidSigner, getFillRelayTx, toAddress, getAssociatedTokenAddress } from "../../arch/svm";
8
+ import {
9
+ SVMProvider,
10
+ SolanaVoidSigner,
11
+ getFillRelayTx,
12
+ toAddress,
13
+ getAssociatedTokenAddress,
14
+ deserializeMessage,
15
+ } from "../../arch/svm";
9
16
  import { Coingecko } from "../../coingecko";
10
17
  import { CHAIN_IDs } from "../../constants";
11
18
  import { getGasPriceEstimate } from "../../gasPriceOracle";
12
19
  import { RelayData } from "../../interfaces";
13
- import { Address, BigNumber, BigNumberish, SvmAddress, TransactionCostEstimate, toBN } from "../../utils";
20
+ import {
21
+ Address,
22
+ BigNumber,
23
+ BigNumberish,
24
+ SvmAddress,
25
+ TransactionCostEstimate,
26
+ bnZero,
27
+ isMessageEmpty,
28
+ toBN,
29
+ } from "../../utils";
14
30
  import { Logger, QueryInterface, getDefaultRelayer } from "../relayFeeCalculator";
15
31
  import { SymbolMappingType } from "./";
16
32
  import { TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
@@ -156,6 +172,20 @@ export class SvmQuery implements QueryInterface {
156
172
  return toBN(await this.computeUnitEstimator(fillRelayTx));
157
173
  }
158
174
 
175
+ /**
176
+ * @notice Return the native token cost of filling a deposit beyond gas cost. If `value_amount` is specified in a message,
177
+ * `value_amount` of SOL gets forwarded to the first Account. We account for that in Fill cost estimation
178
+ * @param deposit RelayData associated with Deposit we're estimating for
179
+ * @throws If deposit.message is malformed (unable to be deserialized into `AcrossPlusMessage`)
180
+ * @returns Native token cost
181
+ */
182
+ getAuxiliaryNativeTokenCost(deposit: RelayData): BigNumber {
183
+ // Notice. We return `message.value_amount` here instead of simulating the Transaction. The reason is, we choose to
184
+ // rely hard on Solana program to protect us from not taking more than `value_amount` rather than relying on
185
+ // simulation. Chain state may change between simulation and execution, so simulation alone is unreliable
186
+ return isMessageEmpty(deposit.message) ? bnZero : BigNumber.from(deserializeMessage(deposit.message).value_amount);
187
+ }
188
+
159
189
  /**
160
190
  * @notice Return the fillRelay transaction for a given deposit
161
191
  * @param relayData RelayData instance, supplemented with destinationChainId
@@ -5,7 +5,7 @@ import {
5
5
  DEFAULT_SIMULATED_RELAYER_ADDRESS_SVM,
6
6
  TOKEN_SYMBOLS_MAP,
7
7
  } from "../constants";
8
- import { RelayData } from "../interfaces";
8
+ import { RelayData, TokenInfo } from "../interfaces";
9
9
  import {
10
10
  BigNumber,
11
11
  BigNumberish,
@@ -46,6 +46,7 @@ export interface QueryInterface {
46
46
  ) => Promise<TransactionCostEstimate>;
47
47
  getTokenPrice: (tokenSymbol: string) => Promise<number>;
48
48
  getNativeGasCost: (deposit: RelayData & { destinationChainId: number }, relayer: Address) => Promise<BigNumber>;
49
+ getAuxiliaryNativeTokenCost(deposit: RelayData): BigNumber;
49
50
  }
50
51
 
51
52
  export const expectedCapitalCostsKeys = ["lowerBound", "upperBound", "cutoff", "decimals"];
@@ -86,6 +87,9 @@ export interface RelayerFeeDetails {
86
87
  gasFeePercent: string;
87
88
  gasFeeTotal: string;
88
89
  gasDiscountPercent: number;
90
+ auxNativeFeePercent: string;
91
+ auxNativeFeeTotal: string;
92
+ auxNativeDiscountPercent: number;
89
93
  capitalFeePercent: string;
90
94
  capitalFeeTotal: string;
91
95
  capitalDiscountPercent: number;
@@ -256,10 +260,10 @@ export class RelayFeeCalculator {
256
260
  async gasFeePercent(
257
261
  deposit: RelayData & { destinationChainId: number },
258
262
  outputAmount: BigNumberish,
263
+ outputTokenInfo: TokenInfo,
259
264
  simulateZeroFill = false,
260
265
  relayerAddress = getDefaultRelayer(deposit.destinationChainId),
261
266
  _tokenPrice?: number,
262
- tokenMapping = TOKEN_SYMBOLS_MAP,
263
267
  gasPrice?: BigNumberish,
264
268
  gasLimit?: BigNumberish,
265
269
  _tokenGasCost?: BigNumberish,
@@ -267,25 +271,6 @@ export class RelayFeeCalculator {
267
271
  ): Promise<BigNumber> {
268
272
  if (toBN(outputAmount).eq(bnZero)) return MAX_BIG_INT;
269
273
 
270
- const { inputToken, destinationChainId, originChainId } = deposit;
271
- // It's fine if we resolve a destination token which is not the "canonical" L1 token (e.g. USDB for DAI or USDC.e for USDC), since `getTokenInfo` will re-map
272
- // the output token to the canonical version. What matters here is that we find an entry in the token map which has defined addresses for BOTH the origin
273
- // and destination chain. This prevents the call to `getTokenInfo` to mistakenly return token info for a token which has a defined address on origin and an
274
- // undefined address on destination.
275
- const destinationChainTokenDetails = Object.values(tokenMapping).find(
276
- (details) =>
277
- compareAddressesSimple(details.addresses[originChainId], inputToken.toNative()) &&
278
- isDefined(details.addresses[destinationChainId])
279
- );
280
- const outputToken = deposit.outputToken.isZeroAddress()
281
- ? toAddressType(destinationChainTokenDetails!.addresses[destinationChainId], destinationChainId)
282
- : deposit.outputToken;
283
- const outputTokenInfo = getTokenInfo(outputToken, destinationChainId, tokenMapping);
284
- const inputTokenInfo = getTokenInfo(inputToken, originChainId, tokenMapping);
285
- if (!isDefined(outputTokenInfo) || !isDefined(inputTokenInfo)) {
286
- throw new Error(`Could not find token information for ${inputToken} or ${outputToken}`);
287
- }
288
-
289
274
  // Reduce the output amount to simulate a full fill with a lower value to estimate
290
275
  // the fill cost accurately without risking a failure due to insufficient balance.
291
276
  const simulatedAmount = simulateZeroFill ? safeOutputAmount : toBN(outputAmount);
@@ -306,22 +291,43 @@ export class RelayFeeCalculator {
306
291
  });
307
292
  const [tokenGasCost, tokenPrice] = await Promise.all([
308
293
  _tokenGasCost ? Promise.resolve(_tokenGasCost) : getGasCosts,
309
- _tokenPrice ??
310
- this.queries.getTokenPrice(outputTokenInfo.symbol).catch((error) => {
311
- this.logger.error({
312
- at: "sdk/gasFeePercent",
313
- message: "Error while fetching token price",
314
- error,
315
- destinationChainId: deposit.destinationChainId,
316
- inputToken,
317
- });
318
- throw error;
319
- }),
294
+ this.resolveTokenPrice(outputTokenInfo, _tokenPrice, deposit),
320
295
  ]);
321
296
  const gasFeesInToken = nativeToToken(tokenGasCost, tokenPrice, outputTokenInfo.decimals, this.nativeTokenDecimals);
322
297
  return percent(gasFeesInToken, outputAmount.toString());
323
298
  }
324
299
 
300
+ /**
301
+ * Calculate the auxiliary native token fee as a % of the amount to relay.
302
+ * Treats auxiliary native outlay as value forwarded to user, reported separately.
303
+ */
304
+ async auxNativeFeePercent(
305
+ deposit: RelayData & { destinationChainId: number },
306
+ outputAmount: BigNumberish,
307
+ outputTokenInfo: TokenInfo,
308
+ _tokenPrice?: number
309
+ ): Promise<BigNumber> {
310
+ if (toBN(outputAmount).eq(bnZero)) return MAX_BIG_INT;
311
+
312
+ let auxNativeCost = bnZero;
313
+ try {
314
+ auxNativeCost = this.queries.getAuxiliaryNativeTokenCost(deposit);
315
+ } catch (error) {
316
+ this.logger.error({
317
+ at: "sdk/auxNativeFeePercent",
318
+ message: "Error while fetching auxiliary native token cost",
319
+ error,
320
+ destinationChainId: deposit.destinationChainId,
321
+ inputToken: deposit.inputToken,
322
+ });
323
+ throw error;
324
+ }
325
+
326
+ const tokenPrice = await this.resolveTokenPrice(outputTokenInfo, _tokenPrice, deposit);
327
+ const auxFeesInToken = nativeToToken(auxNativeCost, tokenPrice, outputTokenInfo.decimals, this.nativeTokenDecimals);
328
+ return percent(auxFeesInToken, outputAmount);
329
+ }
330
+
325
331
  // Note: these variables are unused now, but may be needed in future versions of this function that are more complex.
326
332
  capitalFeePercent(
327
333
  _outputAmount: BigNumberish,
@@ -505,22 +511,17 @@ export class RelayFeeCalculator {
505
511
  // If the amount to relay is not provided, then we
506
512
  // should use the full deposit amount.
507
513
  outputAmount ??= deposit.outputAmount;
508
- const { inputToken, originChainId, outputToken, destinationChainId } = deposit;
509
- // We can perform a simple lookup with `getTokenInfo` here without resolving the exact token to resolve since we only need to
510
- // resolve the L1 token symbol and not the L2 token decimals.
511
- const inputTokenInfo = getTokenInfo(inputToken, originChainId);
512
- const outputTokenInfo = getTokenInfo(outputToken, destinationChainId);
513
- if (!isDefined(inputTokenInfo) || !isDefined(outputTokenInfo)) {
514
- throw new Error(`Could not find token information for ${inputToken} or ${outputToken}`);
515
- }
514
+ const { inputTokenInfo, outputTokenInfo } = this.resolveInOutTokenInfos(deposit);
515
+
516
+ const tokenPrice = await this.resolveTokenPrice(outputTokenInfo, _tokenPrice, deposit);
516
517
 
517
518
  const gasFeePercent = await this.gasFeePercent(
518
519
  deposit,
519
520
  outputAmount,
521
+ outputTokenInfo,
520
522
  simulateZeroFill,
521
523
  relayerAddress,
522
- _tokenPrice,
523
- undefined,
524
+ tokenPrice,
524
525
  gasPrice,
525
526
  gasUnits,
526
527
  tokenGasCost
@@ -534,16 +535,28 @@ export class RelayFeeCalculator {
534
535
  deposit.destinationChainId.toString()
535
536
  );
536
537
  const capitalFeeTotal = capitalFeePercent.mul(outToInDecimals(outputAmount.toString())).div(fixedPointAdjustment);
537
- const relayFeePercent = gasFeePercent.add(capitalFeePercent);
538
- const relayFeeTotal = gasFeeTotal.add(capitalFeeTotal);
539
538
 
540
- // We don't want the relayer to incur an excessive gas fee charge as a % of the deposited total.
541
- // The maximum gas fee % charged is equal to the remaining fee % leftover after subtracting the capital fee %
539
+ const auxNativeFeePercent = await this.auxNativeFeePercent(deposit, outputAmount, outputTokenInfo, tokenPrice);
540
+ const auxNativeFeeTotal = auxNativeFeePercent
541
+ .mul(outToInDecimals(outputAmount.toString()))
542
+ .div(fixedPointAdjustment);
543
+ const auxNativeDiscountPercent = this.gasDiscountPercent;
544
+
545
+ const relayFeePercent = gasFeePercent.add(capitalFeePercent).add(auxNativeFeePercent);
546
+ const relayFeeTotal = gasFeeTotal.add(capitalFeeTotal).add(auxNativeFeeTotal);
547
+
548
+ // We don't want the relayer to incur an excessive gas fee charge as a % of the deposited total. The maximum
549
+ // gas fee % charged is equal to the remaining fee % leftover after subtracting the capital fee % and aux fee %
542
550
  // from the fee limit %. We then compute the minimum deposited amount required to not exceed the maximum
543
551
  // gas fee %: maxGasFeePercent = gasFeeTotal / minDeposit. Refactor this to figure out the minDeposit:
544
552
  // minDeposit = gasFeeTotal / maxGasFeePercent, and subsequently determine
545
553
  // isAmountTooLow = amountToRelay < minDeposit.
546
- const maxGasFeePercent = max(toBNWei(this.feeLimitPercent / 100).sub(capitalFeePercent), toBN(0));
554
+ const maxGasFeePercent = max(
555
+ toBNWei(this.feeLimitPercent / 100)
556
+ .sub(capitalFeePercent)
557
+ .sub(auxNativeFeePercent),
558
+ toBN(0)
559
+ );
547
560
  // If maxGasFee % is 0, then the min deposit should be infinite because there is no deposit amount that would
548
561
  // incur a non zero gas fee % charge. In this case, isAmountTooLow should always be true.
549
562
  let minDeposit: BigNumber, isAmountTooLow: boolean;
@@ -561,6 +574,9 @@ export class RelayFeeCalculator {
561
574
  gasFeePercent: gasFeePercent.toString(),
562
575
  gasFeeTotal: gasFeeTotal.toString(),
563
576
  gasDiscountPercent: this.gasDiscountPercent,
577
+ auxNativeFeePercent: auxNativeFeePercent.toString(),
578
+ auxNativeFeeTotal: auxNativeFeeTotal.toString(),
579
+ auxNativeDiscountPercent,
564
580
  capitalFeePercent: capitalFeePercent.toString(),
565
581
  capitalFeeTotal: capitalFeeTotal.toString(),
566
582
  capitalDiscountPercent: this.capitalDiscountPercent,
@@ -572,4 +588,52 @@ export class RelayFeeCalculator {
572
588
  isAmountTooLow,
573
589
  };
574
590
  }
591
+
592
+ resolveInOutTokenInfos(
593
+ deposit: RelayData & { destinationChainId: number },
594
+ tokenMapping = TOKEN_SYMBOLS_MAP
595
+ ): {
596
+ inputTokenInfo: TokenInfo;
597
+ outputTokenInfo: TokenInfo;
598
+ } {
599
+ const { inputToken, destinationChainId, originChainId } = deposit;
600
+ // It's fine if we resolve a destination token which is not the "canonical" L1 token (e.g. USDB for DAI or USDC.e for USDC), since `getTokenInfo` will re-map
601
+ // the output token to the canonical version. What matters here is that we find an entry in the token map which has defined addresses for BOTH the origin
602
+ // and destination chain. This prevents the call to `getTokenInfo` to mistakenly return token info for a token which has a defined address on origin and an
603
+ // undefined address on destination.
604
+ const destinationChainTokenDetails = Object.values(tokenMapping).find(
605
+ (details) =>
606
+ compareAddressesSimple(details.addresses[originChainId], inputToken.toNative()) &&
607
+ isDefined(details.addresses[destinationChainId])
608
+ );
609
+ const outputToken = deposit.outputToken.isZeroAddress()
610
+ ? toAddressType(destinationChainTokenDetails!.addresses[destinationChainId], destinationChainId)
611
+ : deposit.outputToken;
612
+ const outputTokenInfo = getTokenInfo(outputToken, destinationChainId, tokenMapping);
613
+ const inputTokenInfo = getTokenInfo(inputToken, originChainId, tokenMapping);
614
+ if (!isDefined(outputTokenInfo) || !isDefined(inputTokenInfo)) {
615
+ throw new Error(`Could not find token information for ${inputToken} or ${outputToken}`);
616
+ }
617
+ return { inputTokenInfo, outputTokenInfo };
618
+ }
619
+
620
+ async resolveTokenPrice(
621
+ outputTokenInfo: TokenInfo,
622
+ _tokenPrice: number | undefined,
623
+ deposit: RelayData & { destinationChainId: number }
624
+ ): Promise<number> {
625
+ return (
626
+ _tokenPrice ??
627
+ (await this.queries.getTokenPrice(outputTokenInfo.symbol).catch((error) => {
628
+ this.logger.error({
629
+ at: "sdk/resolveTokenPrice",
630
+ message: "Error while fetching token price",
631
+ error,
632
+ destinationChainId: deposit.destinationChainId,
633
+ inputToken: deposit.inputToken,
634
+ });
635
+ throw error;
636
+ }))
637
+ );
638
+ }
575
639
  }
@@ -59,12 +59,12 @@ export const formatFeePct = (relayerFeePct: BN): string => {
59
59
  /**
60
60
  * Shortens a lengthy hexadecimal string to a shorter version with an ellipsis in the middle.
61
61
  * @param hex A hexadecimal string to be shortened.
62
- * @param maxLength The maximum length of the shortened string. Defaults to 8.
62
+ * @param maxLength The maximum length of the shortened string.
63
63
  * @param delimiter The delimiter to use in the middle of the shortened string. Defaults to "...".
64
64
  * @returns The shortened hexadecimal string.
65
65
  * @example createShortenedString("0x772871a444c6e4e9903d8533a5a13101b74037158123e6709470f0afbf6e7d94") -> "0x7787...7d94"
66
66
  */
67
- export function createShortenedString(hex: string, maxLength = 8, delimiter = ".."): string {
67
+ export function createShortenedString(hex: string, maxLength = 12, delimiter = ".."): string {
68
68
  // If we have more maxLength then the hex size, we can simply
69
69
  // return the hex directly.
70
70
  if (hex.length <= maxLength) {
@@ -32,6 +32,7 @@ const DETERMINISTIC_MULTICALL_CHAINS = [
32
32
  CHAIN_IDs.HYPEREVM,
33
33
  CHAIN_IDs.LINEA,
34
34
  CHAIN_IDs.MAINNET,
35
+ CHAIN_IDs.PLASMA,
35
36
  CHAIN_IDs.POLYGON,
36
37
  CHAIN_IDs.SCROLL,
37
38
  // Testnet:
@@ -39,6 +40,7 @@ const DETERMINISTIC_MULTICALL_CHAINS = [
39
40
  CHAIN_IDs.SCROLL_SEPOLIA,
40
41
  CHAIN_IDs.SEPOLIA,
41
42
  CHAIN_IDs.ARBITRUM_SEPOLIA,
43
+ CHAIN_IDs.PLASMA_TESTNET,
42
44
  CHAIN_IDs.TATARA,
43
45
  ...Object.keys(hreNetworks).map(Number), // See test/utils/multicall.ts
44
46
  ];
@@ -155,7 +155,7 @@ export function chainIsCCTPEnabled(chainId: number): boolean {
155
155
  export function chainIsOFTEnabled(chainId: number): boolean {
156
156
  // Add chainIds to oftEnabled as they are supported by the protocol.
157
157
  // This is backwards vs. CCTP logic because Across support for OFTs is limited vs. OFT deployments.
158
- const oftEnabled = [CHAIN_IDs.ARBITRUM, CHAIN_IDs.POLYGON];
158
+ const oftEnabled = [CHAIN_IDs.ARBITRUM, CHAIN_IDs.POLYGON, CHAIN_IDs.HYPEREVM, CHAIN_IDs.PLASMA];
159
159
  return oftEnabled.includes(chainId) && PRODUCTION_NETWORKS[chainId]?.oftEid !== OFT_NO_EID;
160
160
  }
161
161