@across-protocol/sdk 3.4.19 → 4.0.0-beta.0

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 (163) hide show
  1. package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
  2. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +215 -253
  3. package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  4. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
  5. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +2 -1
  6. package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  7. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +1 -3
  8. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +1 -33
  9. package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  10. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +12 -14
  11. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +3 -3
  12. package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
  13. package/dist/cjs/clients/SpokePoolClient.d.ts +16 -12
  14. package/dist/cjs/clients/SpokePoolClient.js +25 -20
  15. package/dist/cjs/clients/SpokePoolClient.js.map +1 -1
  16. package/dist/cjs/clients/mocks/MockSpokePoolClient.d.ts +5 -7
  17. package/dist/cjs/clients/mocks/MockSpokePoolClient.js +6 -18
  18. package/dist/cjs/clients/mocks/MockSpokePoolClient.js.map +1 -1
  19. package/dist/cjs/constants.d.ts +2 -2
  20. package/dist/cjs/constants.js +3 -3
  21. package/dist/cjs/constants.js.map +1 -1
  22. package/dist/cjs/interfaces/SpokePool.d.ts +2 -2
  23. package/dist/cjs/providers/index.d.ts +0 -1
  24. package/dist/cjs/providers/index.js +0 -2
  25. package/dist/cjs/providers/index.js.map +1 -1
  26. package/dist/cjs/utils/AddressUtils.d.ts +0 -2
  27. package/dist/cjs/utils/AddressUtils.js +1 -19
  28. package/dist/cjs/utils/AddressUtils.js.map +1 -1
  29. package/dist/cjs/utils/BigNumberUtils.d.ts +0 -1
  30. package/dist/cjs/utils/BigNumberUtils.js +1 -5
  31. package/dist/cjs/utils/BigNumberUtils.js.map +1 -1
  32. package/dist/cjs/utils/CachingUtils.js +1 -1
  33. package/dist/cjs/utils/CachingUtils.js.map +1 -1
  34. package/dist/cjs/utils/DepositUtils.d.ts +1 -2
  35. package/dist/cjs/utils/DepositUtils.js +5 -14
  36. package/dist/cjs/utils/DepositUtils.js.map +1 -1
  37. package/dist/cjs/utils/EventUtils.js +0 -20
  38. package/dist/cjs/utils/EventUtils.js.map +1 -1
  39. package/dist/cjs/utils/NetworkUtils.d.ts +0 -1
  40. package/dist/cjs/utils/NetworkUtils.js +1 -6
  41. package/dist/cjs/utils/NetworkUtils.js.map +1 -1
  42. package/dist/cjs/utils/SpokeUtils.d.ts +5 -7
  43. package/dist/cjs/utils/SpokeUtils.js +59 -32
  44. package/dist/cjs/utils/SpokeUtils.js.map +1 -1
  45. package/dist/cjs/utils/ValidatorUtils.js +1 -1
  46. package/dist/cjs/utils/ValidatorUtils.js.map +1 -1
  47. package/dist/cjs/utils/common.d.ts +0 -1
  48. package/dist/cjs/utils/common.js +1 -2
  49. package/dist/cjs/utils/common.js.map +1 -1
  50. package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
  51. package/dist/esm/clients/BundleDataClient/BundleDataClient.js +276 -323
  52. package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
  53. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
  54. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +3 -2
  55. package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -1
  56. package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +1 -3
  57. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +1 -42
  58. package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
  59. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +12 -14
  60. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +4 -4
  61. package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -1
  62. package/dist/esm/clients/SpokePoolClient.d.ts +24 -13
  63. package/dist/esm/clients/SpokePoolClient.js +34 -22
  64. package/dist/esm/clients/SpokePoolClient.js.map +1 -1
  65. package/dist/esm/clients/mocks/MockSpokePoolClient.d.ts +5 -7
  66. package/dist/esm/clients/mocks/MockSpokePoolClient.js +7 -19
  67. package/dist/esm/clients/mocks/MockSpokePoolClient.js.map +1 -1
  68. package/dist/esm/constants.d.ts +2 -2
  69. package/dist/esm/constants.js +2 -2
  70. package/dist/esm/constants.js.map +1 -1
  71. package/dist/esm/interfaces/SpokePool.d.ts +2 -2
  72. package/dist/esm/providers/index.d.ts +0 -1
  73. package/dist/esm/providers/index.js +0 -2
  74. package/dist/esm/providers/index.js.map +1 -1
  75. package/dist/esm/utils/AddressUtils.d.ts +0 -2
  76. package/dist/esm/utils/AddressUtils.js +0 -25
  77. package/dist/esm/utils/AddressUtils.js.map +1 -1
  78. package/dist/esm/utils/BigNumberUtils.d.ts +0 -8
  79. package/dist/esm/utils/BigNumberUtils.js +0 -10
  80. package/dist/esm/utils/BigNumberUtils.js.map +1 -1
  81. package/dist/esm/utils/CachingUtils.js +1 -1
  82. package/dist/esm/utils/CachingUtils.js.map +1 -1
  83. package/dist/esm/utils/DepositUtils.d.ts +1 -2
  84. package/dist/esm/utils/DepositUtils.js +5 -14
  85. package/dist/esm/utils/DepositUtils.js.map +1 -1
  86. package/dist/esm/utils/EventUtils.js +0 -30
  87. package/dist/esm/utils/EventUtils.js.map +1 -1
  88. package/dist/esm/utils/NetworkUtils.d.ts +0 -6
  89. package/dist/esm/utils/NetworkUtils.js +0 -10
  90. package/dist/esm/utils/NetworkUtils.js.map +1 -1
  91. package/dist/esm/utils/SpokeUtils.d.ts +5 -7
  92. package/dist/esm/utils/SpokeUtils.js +61 -34
  93. package/dist/esm/utils/SpokeUtils.js.map +1 -1
  94. package/dist/esm/utils/ValidatorUtils.js +1 -1
  95. package/dist/esm/utils/ValidatorUtils.js.map +1 -1
  96. package/dist/esm/utils/abi/typechain/Multicall3.d.ts +1 -4
  97. package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -1
  98. package/dist/esm/utils/common.d.ts +0 -1
  99. package/dist/esm/utils/common.js +0 -1
  100. package/dist/esm/utils/common.js.map +1 -1
  101. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
  102. package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
  103. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts +2 -1
  104. package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -1
  105. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +1 -3
  106. package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
  107. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +12 -14
  108. package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts.map +1 -1
  109. package/dist/types/clients/SpokePoolClient.d.ts +24 -13
  110. package/dist/types/clients/SpokePoolClient.d.ts.map +1 -1
  111. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts +5 -7
  112. package/dist/types/clients/mocks/MockSpokePoolClient.d.ts.map +1 -1
  113. package/dist/types/constants.d.ts +2 -2
  114. package/dist/types/constants.d.ts.map +1 -1
  115. package/dist/types/interfaces/SpokePool.d.ts +2 -2
  116. package/dist/types/interfaces/SpokePool.d.ts.map +1 -1
  117. package/dist/types/providers/index.d.ts +0 -1
  118. package/dist/types/providers/index.d.ts.map +1 -1
  119. package/dist/types/utils/AddressUtils.d.ts +0 -2
  120. package/dist/types/utils/AddressUtils.d.ts.map +1 -1
  121. package/dist/types/utils/BigNumberUtils.d.ts +0 -8
  122. package/dist/types/utils/BigNumberUtils.d.ts.map +1 -1
  123. package/dist/types/utils/DepositUtils.d.ts +1 -2
  124. package/dist/types/utils/DepositUtils.d.ts.map +1 -1
  125. package/dist/types/utils/EventUtils.d.ts.map +1 -1
  126. package/dist/types/utils/NetworkUtils.d.ts +0 -6
  127. package/dist/types/utils/NetworkUtils.d.ts.map +1 -1
  128. package/dist/types/utils/SpokeUtils.d.ts +5 -7
  129. package/dist/types/utils/SpokeUtils.d.ts.map +1 -1
  130. package/dist/types/utils/abi/typechain/Multicall3.d.ts +1 -4
  131. package/dist/types/utils/abi/typechain/Multicall3.d.ts.map +1 -1
  132. package/dist/types/utils/abi/typechain/common.d.ts.map +1 -1
  133. package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts.map +1 -1
  134. package/dist/types/utils/common.d.ts +0 -1
  135. package/dist/types/utils/common.d.ts.map +1 -1
  136. package/package.json +2 -2
  137. package/src/clients/BundleDataClient/BundleDataClient.ts +238 -309
  138. package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +8 -0
  139. package/src/clients/BundleDataClient/utils/FillUtils.ts +2 -47
  140. package/src/clients/BundleDataClient/utils/SuperstructUtils.ts +2 -4
  141. package/src/clients/SpokePoolClient.ts +44 -31
  142. package/src/clients/mocks/MockSpokePoolClient.ts +10 -25
  143. package/src/constants.ts +2 -2
  144. package/src/interfaces/SpokePool.ts +2 -2
  145. package/src/providers/index.ts +0 -1
  146. package/src/utils/AddressUtils.ts +0 -26
  147. package/src/utils/BigNumberUtils.ts +0 -11
  148. package/src/utils/CachingUtils.ts +1 -1
  149. package/src/utils/DepositUtils.ts +5 -14
  150. package/src/utils/EventUtils.ts +0 -31
  151. package/src/utils/NetworkUtils.ts +0 -11
  152. package/src/utils/SpokeUtils.ts +60 -52
  153. package/src/utils/ValidatorUtils.ts +1 -1
  154. package/src/utils/common.ts +0 -2
  155. package/dist/cjs/providers/mockProvider.d.ts +0 -19
  156. package/dist/cjs/providers/mockProvider.js +0 -70
  157. package/dist/cjs/providers/mockProvider.js.map +0 -1
  158. package/dist/esm/providers/mockProvider.d.ts +0 -23
  159. package/dist/esm/providers/mockProvider.js +0 -73
  160. package/dist/esm/providers/mockProvider.js.map +0 -1
  161. package/dist/types/providers/mockProvider.d.ts +0 -24
  162. package/dist/types/providers/mockProvider.d.ts.map +0 -1
  163. package/src/providers/mockProvider.ts +0 -77
@@ -14,6 +14,7 @@ import {
14
14
  import {
15
15
  bnZero,
16
16
  AnyObject,
17
+ groupObjectCountsByTwoProps,
17
18
  fixedPointAdjustment,
18
19
  count2DDictionaryValues,
19
20
  count3DDictionaryValues,
@@ -25,6 +26,7 @@ import {
25
26
  updateRunningBalance,
26
27
  updateRunningBalanceForDeposit,
27
28
  } from "./PoolRebalanceUtils";
29
+ import { V3FillWithBlock } from "./shims";
28
30
  import { AcrossConfigStoreClient } from "../../AcrossConfigStoreClient";
29
31
  import { HubPoolClient } from "../../HubPoolClient";
30
32
  import { buildPoolRebalanceLeafTree } from "./MerkleTreeUtils";
@@ -81,6 +83,7 @@ export function getRefundsFromBundle(
81
83
  export function prettyPrintV3SpokePoolEvents(
82
84
  bundleDepositsV3: BundleDepositsV3,
83
85
  bundleFillsV3: BundleFillsV3,
86
+ bundleInvalidFillsV3: V3FillWithBlock[],
84
87
  bundleSlowFillsV3: BundleSlowFills,
85
88
  expiredDepositsToRefundV3: ExpiredDepositsToRefundV3,
86
89
  unexecutableSlowFills: BundleExcessSlowFills
@@ -91,6 +94,11 @@ export function prettyPrintV3SpokePoolEvents(
91
94
  bundleSlowFillsV3: count2DDictionaryValues(bundleSlowFillsV3),
92
95
  expiredDepositsToRefundV3: count2DDictionaryValues(expiredDepositsToRefundV3),
93
96
  unexecutableSlowFills: count2DDictionaryValues(unexecutableSlowFills),
97
+ allInvalidFillsInRangeByDestinationChainAndRelayer: groupObjectCountsByTwoProps(
98
+ bundleInvalidFillsV3,
99
+ "destinationChainId",
100
+ (fill) => `${fill.relayer}`
101
+ ),
94
102
  };
95
103
  }
96
104
 
@@ -1,7 +1,5 @@
1
- import _ from "lodash";
2
- import { providers } from "ethers";
3
- import { DepositWithBlock, Fill, FillWithBlock } from "../../../interfaces";
4
- import { getBlockRangeForChain, isSlowFill, chainIsEvm, isValidEvmAddress, isDefined } from "../../../utils";
1
+ import { Fill } from "../../../interfaces";
2
+ import { getBlockRangeForChain, isSlowFill } from "../../../utils";
5
3
  import { HubPoolClient } from "../../HubPoolClient";
6
4
 
7
5
  export function getRefundInformationFromFill(
@@ -46,46 +44,3 @@ export function getRefundInformationFromFill(
46
44
  repaymentToken,
47
45
  };
48
46
  }
49
-
50
- // Verify that a fill sent to an EVM chain has a 20 byte address. If the fill does not, then attempt
51
- // to repay the `msg.sender` of the relay transaction. Otherwise, return undefined.
52
- export async function verifyFillRepayment(
53
- fill: FillWithBlock,
54
- destinationChainProvider: providers.Provider,
55
- matchedDeposit: DepositWithBlock,
56
- possibleRepaymentChainIds: number[]
57
- ): Promise<FillWithBlock | undefined> {
58
- // Slow fills don't result in repayments so they're always valid.
59
- if (isSlowFill(fill)) {
60
- return fill;
61
- }
62
- // Lite chain deposits force repayment on origin chain.
63
- const repaymentChainId = matchedDeposit.fromLiteChain ? fill.originChainId : fill.repaymentChainId;
64
- // Return undefined if the requested repayment chain ID is not recognized by the hub pool.
65
- if (!possibleRepaymentChainIds.includes(repaymentChainId)) {
66
- return undefined;
67
- }
68
- const updatedFill = _.cloneDeep(fill);
69
-
70
- // If the fill requests repayment on a chain where the repayment address is not valid, attempt to find a valid
71
- // repayment address, otherwise return undefined.
72
-
73
- // Case 1: repayment chain is an EVM chain but repayment address is not a valid EVM address.
74
- if (chainIsEvm(repaymentChainId) && !isValidEvmAddress(updatedFill.relayer)) {
75
- // TODO: Handle case where fill was sent on non-EVM chain, in which case the following call would fail
76
- // or return something unexpected. We'd want to return undefined here.
77
- const fillTransaction = await destinationChainProvider.getTransaction(updatedFill.transactionHash);
78
- const destinationRelayer = fillTransaction?.from;
79
- // Repayment chain is still an EVM chain, but the msg.sender is a bytes32 address, so the fill is invalid.
80
- if (!isDefined(destinationRelayer) || !isValidEvmAddress(destinationRelayer)) {
81
- return undefined;
82
- }
83
- // Otherwise, assume the relayer to be repaid is the msg.sender. We don't need to modify the repayment chain since
84
- // the getTransaction() call would only succeed if the fill was sent on an EVM chain and therefore the msg.sender
85
- // is a valid EVM address and the repayment chain is an EVM chain.
86
- updatedFill.relayer = destinationRelayer;
87
- }
88
-
89
- // Case 2: TODO repayment chain is an SVM chain and repayment address is not a valid SVM address.
90
- return updatedFill;
91
- }
@@ -10,7 +10,6 @@ import {
10
10
  pattern,
11
11
  boolean,
12
12
  defaulted,
13
- union,
14
13
  type,
15
14
  } from "superstruct";
16
15
  import { BigNumber } from "../../../utils";
@@ -18,7 +17,7 @@ import { BigNumber } from "../../../utils";
18
17
  const PositiveIntegerStringSS = pattern(string(), /\d+/);
19
18
  const Web3AddressSS = pattern(string(), /^0x[a-fA-F0-9]{40}$/);
20
19
 
21
- const BigNumberType = coerce(instance(BigNumber), union([string(), number()]), (value) => {
20
+ const BigNumberType = coerce(instance(BigNumber), string(), (value) => {
22
21
  try {
23
22
  // Attempt to convert the string to a BigNumber
24
23
  return BigNumber.from(value);
@@ -42,7 +41,7 @@ const V3RelayDataSS = {
42
41
  originChainId: number(),
43
42
  depositor: string(),
44
43
  recipient: string(),
45
- depositId: BigNumberType,
44
+ depositId: number(),
46
45
  message: string(),
47
46
  };
48
47
 
@@ -92,7 +91,6 @@ const V3FillSS = {
92
91
  repaymentChainId: number(),
93
92
  relayExecutionInfo: V3RelayExecutionEventInfoSS,
94
93
  quoteTimestamp: number(),
95
- messageHash: optional(string()),
96
94
  };
97
95
 
98
96
  const V3FillWithBlockSS = {
@@ -12,8 +12,6 @@ import {
12
12
  getRelayDataHash,
13
13
  isDefined,
14
14
  toBN,
15
- bnOne,
16
- isUnsafeDepositId,
17
15
  } from "../utils";
18
16
  import {
19
17
  paginatedEventQuery,
@@ -48,8 +46,8 @@ type SpokePoolUpdateSuccess = {
48
46
  success: true;
49
47
  currentTime: number;
50
48
  oldestTime: number;
51
- firstDepositId: BigNumber;
52
- latestDepositId: BigNumber;
49
+ firstDepositId: number;
50
+ latestDepositId: number;
53
51
  events: Log[][];
54
52
  searchEndBlock: number;
55
53
  };
@@ -67,8 +65,9 @@ export class SpokePoolClient extends BaseAbstractClient {
67
65
  protected currentTime = 0;
68
66
  protected oldestTime = 0;
69
67
  protected depositHashes: { [depositHash: string]: DepositWithBlock } = {};
68
+ protected duplicateDepositHashes: { [depositHash: string]: DepositWithBlock[] } = {};
70
69
  protected depositHashesToFills: { [depositHash: string]: FillWithBlock[] } = {};
71
- protected speedUps: { [depositorAddress: string]: { [depositId: string]: SpeedUpWithBlock[] } } = {};
70
+ protected speedUps: { [depositorAddress: string]: { [depositId: number]: SpeedUpWithBlock[] } } = {};
72
71
  protected slowFillRequests: { [relayDataHash: string]: SlowFillRequestWithBlock } = {};
73
72
  protected depositRoutes: { [originToken: string]: { [DestinationChainId: number]: boolean } } = {};
74
73
  protected tokensBridged: TokensBridged[] = [];
@@ -76,10 +75,10 @@ export class SpokePoolClient extends BaseAbstractClient {
76
75
  protected relayerRefundExecutions: RelayerRefundExecutionWithBlock[] = [];
77
76
  protected queryableEventNames: string[] = [];
78
77
  protected configStoreClient: AcrossConfigStoreClient | undefined;
79
- public earliestDepositIdQueried = MAX_BIG_INT;
80
- public latestDepositIdQueried = bnZero;
81
- public firstDepositIdForSpokePool = MAX_BIG_INT;
82
- public lastDepositIdForSpokePool = MAX_BIG_INT;
78
+ public earliestDepositIdQueried = Number.MAX_SAFE_INTEGER;
79
+ public latestDepositIdQueried = 0;
80
+ public firstDepositIdForSpokePool = Number.MAX_SAFE_INTEGER;
81
+ public lastDepositIdForSpokePool = Number.MAX_SAFE_INTEGER;
83
82
  public fills: { [OriginChainId: number]: FillWithBlock[] } = {};
84
83
 
85
84
  /**
@@ -126,7 +125,7 @@ export class SpokePoolClient extends BaseAbstractClient {
126
125
  }
127
126
 
128
127
  /**
129
- * Retrieves a list of deposits from the SpokePool contract destined for the given destination chain ID.
128
+ * Retrieves a list of unique deposits from the SpokePool contract destined for the given destination chain ID.
130
129
  * @param destinationChainId The destination chain ID.
131
130
  * @returns A list of deposits.
132
131
  */
@@ -134,6 +133,21 @@ export class SpokePoolClient extends BaseAbstractClient {
134
133
  return Object.values(this.depositHashes).filter((deposit) => deposit.destinationChainId === destinationChainId);
135
134
  }
136
135
 
136
+ /**
137
+ * Returns a list of all deposits including any duplicate ones. Designed only to be used in use cases where
138
+ * all deposits are required, regardless of duplicates. For example, the Dataworker can use this to refund
139
+ * expired deposits including for duplicates.
140
+ * @param destinationChainId
141
+ * @returns A list of deposits
142
+ */
143
+ public getDepositsForDestinationChainWithDuplicates(destinationChainId: number): DepositWithBlock[] {
144
+ const deposits = this.getDepositsForDestinationChain(destinationChainId);
145
+ const duplicateDeposits = Object.values(this.duplicateDepositHashes).filter(
146
+ (deposits) => deposits.length > 0 && deposits[0].destinationChainId === destinationChainId
147
+ );
148
+ return sortEventsAscendingInPlace(deposits.concat(duplicateDeposits.flat()));
149
+ }
150
+
137
151
  /**
138
152
  * Retrieves a list of deposits from the SpokePool contract that are associated with this spoke pool.
139
153
  * @returns A list of deposits.
@@ -234,7 +248,7 @@ export class SpokePoolClient extends BaseAbstractClient {
234
248
  */
235
249
  public appendMaxSpeedUpSignatureToDeposit(deposit: DepositWithBlock): DepositWithBlock {
236
250
  const { depositId, depositor } = deposit;
237
- const speedups = this.speedUps[depositor]?.[depositId.toString()];
251
+ const speedups = this.speedUps[depositor]?.[depositId];
238
252
  if (!isDefined(speedups) || speedups.length === 0) {
239
253
  return deposit;
240
254
  }
@@ -267,7 +281,7 @@ export class SpokePoolClient extends BaseAbstractClient {
267
281
  * @param depositId The unique ID of the deposit being queried.
268
282
  * @returns The corresponding deposit if found, undefined otherwise.
269
283
  */
270
- public getDeposit(depositId: BigNumber): DepositWithBlock | undefined {
284
+ public getDeposit(depositId: number): DepositWithBlock | undefined {
271
285
  const depositHash = this.getDepositHash({ depositId, originChainId: this.chainId });
272
286
  return this.depositHashes[depositHash];
273
287
  }
@@ -297,7 +311,7 @@ export class SpokePoolClient extends BaseAbstractClient {
297
311
  * Retrieves speed up requests grouped by depositor and depositId.
298
312
  * @returns A mapping of depositor addresses to deposit ids with their corresponding speed up requests.
299
313
  */
300
- public getSpeedUps(): { [depositorAddress: string]: { [depositId: string]: SpeedUpWithBlock[] } } {
314
+ public getSpeedUps(): { [depositorAddress: string]: { [depositId: number]: SpeedUpWithBlock[] } } {
301
315
  return this.speedUps;
302
316
  }
303
317
 
@@ -315,7 +329,7 @@ export class SpokePoolClient extends BaseAbstractClient {
315
329
 
316
330
  this.logger.debug({
317
331
  at: "SpokePoolClient::getDepositForFill",
318
- message: `Rejected fill for ${getNetworkName(fill.originChainId)} deposit ${fill.depositId.toString()}.`,
332
+ message: `Rejected fill for ${getNetworkName(fill.originChainId)} deposit ${fill.depositId}.`,
319
333
  reason: match.reason,
320
334
  deposit,
321
335
  fill,
@@ -367,7 +381,7 @@ export class SpokePoolClient extends BaseAbstractClient {
367
381
  );
368
382
 
369
383
  // Log any invalid deposits with same deposit id but different params.
370
- const invalidFillsForDeposit = invalidFills.filter((x) => x.depositId.eq(deposit.depositId));
384
+ const invalidFillsForDeposit = invalidFills.filter((x) => x.depositId === deposit.depositId);
371
385
  if (invalidFillsForDeposit.length > 0) {
372
386
  this.logger.warn({
373
387
  at: "SpokePoolClient",
@@ -398,8 +412,8 @@ export class SpokePoolClient extends BaseAbstractClient {
398
412
  * @note This hash is used to match deposits and fills together.
399
413
  * @note This hash takes the form of: `${depositId}-${originChainId}`.
400
414
  */
401
- public getDepositHash(event: { depositId: BigNumber; originChainId: number }): string {
402
- return `${event.depositId.toString()}-${event.originChainId}`;
415
+ public getDepositHash(event: { depositId: number; originChainId: number }): string {
416
+ return `${event.depositId}-${event.originChainId}`;
403
417
  }
404
418
 
405
419
  /**
@@ -407,7 +421,7 @@ export class SpokePoolClient extends BaseAbstractClient {
407
421
  * @param blockTag The block number to search for the deposit ID at.
408
422
  * @returns The deposit ID.
409
423
  */
410
- public _getDepositIdAtBlock(blockTag: number): Promise<BigNumber> {
424
+ public _getDepositIdAtBlock(blockTag: number): Promise<number> {
411
425
  return getDepositIdAtBlock(this.spokePool as SpokePool, blockTag);
412
426
  }
413
427
 
@@ -440,11 +454,10 @@ export class SpokePoolClient extends BaseAbstractClient {
440
454
  */
441
455
  protected async _update(eventsToQuery: string[]): Promise<SpokePoolUpdate> {
442
456
  // Find the earliest known depositId. This assumes no deposits were placed in the deployment block.
443
- let firstDepositId = this.firstDepositIdForSpokePool;
444
- if (firstDepositId.eq(MAX_BIG_INT)) {
457
+ let firstDepositId: number = this.firstDepositIdForSpokePool;
458
+ if (firstDepositId === Number.MAX_SAFE_INTEGER) {
445
459
  firstDepositId = await this.spokePool.numberOfDeposits({ blockTag: this.deploymentBlock });
446
- firstDepositId = BigNumber.from(firstDepositId); // Cast input to a big number.
447
- if (!BigNumber.isBigNumber(firstDepositId) || firstDepositId.lt(bnZero)) {
460
+ if (isNaN(firstDepositId) || firstDepositId < 0) {
448
461
  throw new Error(`SpokePoolClient::update: Invalid first deposit id (${firstDepositId})`);
449
462
  }
450
463
  }
@@ -494,10 +507,9 @@ export class SpokePoolClient extends BaseAbstractClient {
494
507
  ]);
495
508
  this.log("debug", `Time to query new events from RPC for ${this.chainId}: ${Date.now() - timerStart} ms`);
496
509
 
497
- const [currentTime, _numberOfDeposits] = multicallFunctions.map(
510
+ const [currentTime, numberOfDeposits] = multicallFunctions.map(
498
511
  (fn, idx) => spokePool.interface.decodeFunctionResult(fn, multicallOutput[idx])[0]
499
512
  );
500
- const _latestDepositId = BigNumber.from(_numberOfDeposits).sub(bnOne);
501
513
 
502
514
  if (!BigNumber.isBigNumber(currentTime) || currentTime.lt(this.currentTime)) {
503
515
  const errMsg = BigNumber.isBigNumber(currentTime)
@@ -514,7 +526,7 @@ export class SpokePoolClient extends BaseAbstractClient {
514
526
  currentTime: currentTime.toNumber(), // uint32
515
527
  oldestTime: oldestTime.toNumber(),
516
528
  firstDepositId,
517
- latestDepositId: _latestDepositId.gt(bnZero) ? _latestDepositId : bnZero,
529
+ latestDepositId: Math.max(numberOfDeposits - 1, 0),
518
530
  searchEndBlock: searchConfig.toBlock,
519
531
  events,
520
532
  };
@@ -579,14 +591,15 @@ export class SpokePoolClient extends BaseAbstractClient {
579
591
  }
580
592
 
581
593
  if (this.depositHashes[this.getDepositHash(deposit)] !== undefined) {
594
+ assign(this.duplicateDepositHashes, [this.getDepositHash(deposit)], [deposit]);
582
595
  continue;
583
596
  }
584
597
  assign(this.depositHashes, [this.getDepositHash(deposit)], deposit);
585
598
 
586
- if (deposit.depositId.lt(this.earliestDepositIdQueried) && !isUnsafeDepositId(deposit.depositId)) {
599
+ if (deposit.depositId < this.earliestDepositIdQueried) {
587
600
  this.earliestDepositIdQueried = deposit.depositId;
588
601
  }
589
- if (deposit.depositId.gt(this.latestDepositIdQueried) && !isUnsafeDepositId(deposit.depositId)) {
602
+ if (deposit.depositId > this.latestDepositIdQueried) {
590
603
  this.latestDepositIdQueried = deposit.depositId;
591
604
  }
592
605
  }
@@ -598,7 +611,7 @@ export class SpokePoolClient extends BaseAbstractClient {
598
611
 
599
612
  for (const event of speedUpEvents) {
600
613
  const speedUp = { ...spreadEventWithBlockNumber(event), originChainId: this.chainId } as SpeedUpWithBlock;
601
- assign(this.speedUps, [speedUp.depositor, speedUp.depositId.toString()], [speedUp]);
614
+ assign(this.speedUps, [speedUp.depositor, speedUp.depositId], [speedUp]);
602
615
 
603
616
  // Find deposit hash matching this speed up event and update the deposit data associated with the hash,
604
617
  // if the hash+data exists.
@@ -782,7 +795,7 @@ export class SpokePoolClient extends BaseAbstractClient {
782
795
  return this.oldestTime;
783
796
  }
784
797
 
785
- async findDeposit(depositId: BigNumber, destinationChainId: number): Promise<DepositWithBlock> {
798
+ async findDeposit(depositId: number, destinationChainId: number): Promise<DepositWithBlock> {
786
799
  // Binary search for event search bounds. This way we can get the blocks before and after the deposit with
787
800
  // deposit ID = fill.depositId and use those blocks to optimize the search for that deposit.
788
801
  // Stop searches after a maximum # of searches to limit number of eth_call requests. Make an
@@ -811,12 +824,12 @@ export class SpokePoolClient extends BaseAbstractClient {
811
824
  );
812
825
  const tStop = Date.now();
813
826
 
814
- const event = query.find(({ args }) => args["depositId"].eq(depositId));
827
+ const event = query.find(({ args }) => args["depositId"] === depositId);
815
828
  if (event === undefined) {
816
829
  const srcChain = getNetworkName(this.chainId);
817
830
  const dstChain = getNetworkName(destinationChainId);
818
831
  throw new Error(
819
- `Could not find deposit ${depositId.toString()} for ${dstChain} fill` +
832
+ `Could not find deposit ${depositId} for ${dstChain} fill` +
820
833
  ` between ${srcChain} blocks [${searchBounds.low}, ${searchBounds.high}]`
821
834
  );
822
835
  }
@@ -13,9 +13,8 @@ import {
13
13
  FillWithBlock,
14
14
  SlowFillLeaf,
15
15
  SpeedUp,
16
- TokensBridged,
17
16
  } from "../../interfaces";
18
- import { toBN, toBNWei, getCurrentTime, randomAddress, BigNumber, bnZero, bnOne, bnMax } from "../../utils";
17
+ import { toBN, toBNWei, getCurrentTime, randomAddress } from "../../utils";
19
18
  import { SpokePoolClient, SpokePoolUpdate } from "../SpokePoolClient";
20
19
  import { HubPoolClient } from "../HubPoolClient";
21
20
  import { EventManager, EventOverrides, getEventManager } from "./MockEvents";
@@ -27,8 +26,8 @@ export class MockSpokePoolClient extends SpokePoolClient {
27
26
  public eventManager: EventManager;
28
27
  private destinationTokenForChainOverride: Record<number, string> = {};
29
28
  // Allow tester to set the numberOfDeposits() returned by SpokePool at a block height.
30
- public depositIdAtBlock: BigNumber[] = [];
31
- public numberOfDeposits = bnZero;
29
+ public depositIdAtBlock: number[] = [];
30
+ public numberOfDeposits = 0;
32
31
 
33
32
  constructor(
34
33
  logger: winston.Logger,
@@ -58,21 +57,21 @@ export class MockSpokePoolClient extends SpokePoolClient {
58
57
  this.latestBlockSearched = blockNumber;
59
58
  }
60
59
 
61
- setDepositIds(_depositIds: BigNumber[]): void {
60
+ setDepositIds(_depositIds: number[]): void {
62
61
  this.depositIdAtBlock = [];
63
62
  if (_depositIds.length === 0) {
64
63
  return;
65
64
  }
66
65
  let lastDepositId = _depositIds[0];
67
66
  for (let i = 0; i < _depositIds.length; i++) {
68
- if (_depositIds[i].lt(lastDepositId)) {
67
+ if (_depositIds[i] < lastDepositId) {
69
68
  throw new Error("deposit ID must be equal to or greater than previous");
70
69
  }
71
70
  this.depositIdAtBlock[i] = _depositIds[i];
72
71
  lastDepositId = _depositIds[i];
73
72
  }
74
73
  }
75
- _getDepositIdAtBlock(blockTag: number): Promise<BigNumber> {
74
+ _getDepositIdAtBlock(blockTag: number): Promise<number> {
76
75
  return Promise.resolve(this.depositIdAtBlock[blockTag]);
77
76
  }
78
77
 
@@ -97,13 +96,13 @@ export class MockSpokePoolClient extends SpokePoolClient {
97
96
  // Update latestDepositIdQueried.
98
97
  const idx = eventsToQuery.indexOf("V3FundsDeposited");
99
98
  const latestDepositId = (events[idx] ?? []).reduce(
100
- (depositId, event) => bnMax(depositId, event.args["depositId"] ?? bnZero),
99
+ (depositId, event) => Math.max(depositId, (event.args["depositId"] ?? 0) as number),
101
100
  this.latestDepositIdQueried
102
101
  );
103
102
 
104
103
  return Promise.resolve({
105
104
  success: true,
106
- firstDepositId: bnZero,
105
+ firstDepositId: 0,
107
106
  latestDepositId,
108
107
  currentTime,
109
108
  oldestTime: 0,
@@ -123,8 +122,7 @@ export class MockSpokePoolClient extends SpokePoolClient {
123
122
  const { blockNumber, transactionIndex } = deposit;
124
123
  let { depositId, depositor, destinationChainId, inputToken, inputAmount, outputToken, outputAmount } = deposit;
125
124
  depositId ??= this.numberOfDeposits;
126
- assert(depositId.gte(this.numberOfDeposits), `${depositId.toString()} < ${this.numberOfDeposits}`);
127
- this.numberOfDeposits = depositId.add(bnOne);
125
+ this.numberOfDeposits = depositId + 1;
128
126
 
129
127
  destinationChainId ??= random(1, 42161, false);
130
128
  depositor ??= randomAddress();
@@ -169,7 +167,7 @@ export class MockSpokePoolClient extends SpokePoolClient {
169
167
  const { blockNumber, transactionIndex } = fill;
170
168
  let { originChainId, depositId, inputToken, inputAmount, outputAmount, fillDeadline, relayer } = fill;
171
169
  originChainId ??= random(1, 42161, false);
172
- depositId ??= BigNumber.from(random(1, 100_000, false));
170
+ depositId ??= random(1, 100_000, false);
173
171
  inputToken ??= randomAddress();
174
172
  inputAmount ??= toBNWei(random(1, 1000, false));
175
173
  outputAmount ??= inputAmount;
@@ -226,19 +224,6 @@ export class MockSpokePoolClient extends SpokePoolClient {
226
224
  });
227
225
  }
228
226
 
229
- setTokensBridged(tokensBridged: TokensBridged): Log {
230
- const event = "TokensBridged";
231
- const topics = [tokensBridged.chainId, tokensBridged.leafId, tokensBridged.l2TokenAddress];
232
- const args = { ...tokensBridged };
233
-
234
- return this.eventManager.generateEvent({
235
- event,
236
- address: this.spokePool.address,
237
- topics: topics.map((topic) => topic.toString()),
238
- args,
239
- });
240
- }
241
-
242
227
  requestV3SlowFill(request: SlowFillRequestWithBlock): Log {
243
228
  const event = "RequestedV3SlowFill";
244
229
 
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, HashZero: ZERO_BYTES } = ethersConstants;
13
+ export const { AddressZero: ZERO_ADDRESS } = 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 = 3;
36
+ export const ARWEAVE_TAG_APP_VERSION = 2;
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: BigNumber;
13
+ depositId: number;
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: BigNumber;
70
+ depositId: number;
71
71
  originChainId: number;
72
72
  updatedRecipient: string;
73
73
  updatedOutputAmount: BigNumber;
@@ -5,4 +5,3 @@ export * from "./speedProvider";
5
5
  export * from "./constants";
6
6
  export * from "./types";
7
7
  export * from "./utils";
8
- export * as mocks from "./mockProvider";
@@ -38,29 +38,3 @@ export function compareAddressesSimple(addressA?: string, addressB?: string): bo
38
38
  }
39
39
  return addressA.toLowerCase() === addressB.toLowerCase();
40
40
  }
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
-
52
- export function isValidEvmAddress(address: string): boolean {
53
- if (utils.isAddress(address)) {
54
- return true;
55
- }
56
- // We may throw an error here if hexZeroPadFails. This will happen if the address to pad is greater than 20 bytes long, indicating
57
- // that the address had less than 12 leading zero bytes.
58
- // We may also throw at getAddress if the input cannot be converted into a checksummed EVM address for some reason.
59
- // For both cases, this indicates that the address cannot be casted as a bytes20 EVM address, so we should return false.
60
- try {
61
- const evmAddress = utils.hexZeroPad(utils.hexStripZeros(address), 20);
62
- return utils.isAddress(utils.getAddress(evmAddress));
63
- } catch (_e) {
64
- return false;
65
- }
66
- }
@@ -62,14 +62,3 @@ 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,5 +52,5 @@ export async function setDepositInCache(
52
52
  */
53
53
  export function getDepositKey(bridgeEvent: Deposit | Fill | SlowFillRequest): string {
54
54
  const relayHash = getRelayHashFromEvent(bridgeEvent);
55
- return `deposit_${bridgeEvent.originChainId}_${bridgeEvent.depositId.toString()}_${relayHash}`;
55
+ return `deposit_${bridgeEvent.originChainId}_${bridgeEvent.depositId}_${relayHash}`;
56
56
  }
@@ -5,7 +5,6 @@ import { CachingMechanismInterface, Deposit, DepositWithBlock, Fill, SlowFillReq
5
5
  import { getNetworkName } from "./NetworkUtils";
6
6
  import { getDepositInCache, getDepositKey, setDepositInCache } from "./CachingUtils";
7
7
  import { validateFillForDeposit } from "./FlowUtils";
8
- import { isUnsafeDepositId } from "./SpokeUtils";
9
8
  import { getCurrentTime } from "./TimeUtils";
10
9
  import { isDefined } from "./TypeGuards";
11
10
  import { isDepositFormedCorrectly } from "./ValidatorUtils";
@@ -18,7 +17,6 @@ export enum InvalidFill {
18
17
  DepositIdInvalid = 0, // Deposit ID seems invalid for origin SpokePool
19
18
  DepositIdNotFound, // Deposit ID not found (bad RPC data?)
20
19
  FillMismatch, // Fill does not match deposit parameters for deposit ID.
21
- DepositIdOutOfRange, // Fill is for a deterministic deposit.
22
20
  }
23
21
 
24
22
  export type DepositSearchResult =
@@ -42,13 +40,6 @@ export async function queryHistoricalDepositForFill(
42
40
  fill: Fill | SlowFillRequest,
43
41
  cache?: CachingMechanismInterface
44
42
  ): Promise<DepositSearchResult> {
45
- if (isUnsafeDepositId(fill.depositId)) {
46
- return {
47
- found: false,
48
- code: InvalidFill.DepositIdOutOfRange,
49
- reason: `Cannot find historical deposit for fill with unsafe deposit ID ${fill.depositId}.`,
50
- };
51
- }
52
43
  if (fill.originChainId !== spokePoolClient.chainId) {
53
44
  throw new Error(`OriginChainId mismatch (${fill.originChainId} != ${spokePoolClient.chainId})`);
54
45
  }
@@ -61,16 +52,16 @@ export async function queryHistoricalDepositForFill(
61
52
 
62
53
  const { depositId } = fill;
63
54
  let { firstDepositIdForSpokePool: lowId, lastDepositIdForSpokePool: highId } = spokePoolClient;
64
- if (depositId.lt(lowId) || depositId.gt(highId)) {
55
+ if (depositId < lowId || depositId > highId) {
65
56
  return {
66
57
  found: false,
67
58
  code: InvalidFill.DepositIdInvalid,
68
- reason: `Deposit ID ${depositId.toString()} is outside of SpokePool bounds [${lowId},${highId}].`,
59
+ reason: `Deposit ID ${depositId} is outside of SpokePool bounds [${lowId},${highId}].`,
69
60
  };
70
61
  }
71
62
 
72
63
  ({ earliestDepositIdQueried: lowId, latestDepositIdQueried: highId } = spokePoolClient);
73
- if (depositId.gte(lowId) && depositId.lte(highId)) {
64
+ if (depositId >= lowId && depositId <= highId) {
74
65
  const originChain = getNetworkName(fill.originChainId);
75
66
  const deposit = spokePoolClient.getDeposit(depositId);
76
67
  if (isDefined(deposit)) {
@@ -82,14 +73,14 @@ export async function queryHistoricalDepositForFill(
82
73
  return {
83
74
  found: false,
84
75
  code: InvalidFill.FillMismatch,
85
- reason: `Fill for ${originChain} deposit ID ${depositId.toString()} is invalid (${match.reason}).`,
76
+ reason: `Fill for ${originChain} deposit ID ${depositId} is invalid (${match.reason}).`,
86
77
  };
87
78
  }
88
79
 
89
80
  return {
90
81
  found: false,
91
82
  code: InvalidFill.DepositIdNotFound,
92
- reason: `${originChain} deposit ID ${depositId.toString()} not found in SpokePoolClient event buffer.`,
83
+ reason: `${originChain} deposit ID ${depositId} not found in SpokePoolClient event buffer.`,
93
84
  };
94
85
  }
95
86
 
@@ -3,27 +3,10 @@ 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, toAddress } from "./";
7
6
 
8
7
  const maxRetries = 3;
9
8
  const retrySleepTime = 10;
10
9
 
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
-
27
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
11
  export function spreadEvent(args: Result | Record<string, unknown>): { [key: string]: any } {
29
12
  const keys = Object.keys(args).filter((key: string) => isNaN(+key)); // Extract non-numeric keys.
@@ -75,20 +58,6 @@ export function spreadEvent(args: Result | Record<string, unknown>): { [key: str
75
58
  if (returnedObject.rootBundleId) {
76
59
  returnedObject.rootBundleId = Number(returnedObject.rootBundleId);
77
60
  }
78
- // If depositId is included in the event, cast it to a BigNumber. Need to check if it is defined since the deposit ID can
79
- // be 0, which would still make this evaluate as false.
80
- if (isDefined(returnedObject.depositId)) {
81
- // 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`),
82
- // or a uint256 (and therefore an ethers BigNumber).
83
- returnedObject.depositId = toBN(returnedObject.depositId as BigNumberish);
84
- }
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
- returnedObject[field] = toAddress(String(returnedObject[field]));
90
- }
91
- }
92
61
 
93
62
  return returnedObject;
94
63
  }