@across-protocol/sdk 3.4.14 → 3.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +179 -111
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +3 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +33 -1
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/cjs/providers/index.d.ts +1 -0
- package/dist/cjs/providers/index.js +2 -0
- package/dist/cjs/providers/index.js.map +1 -1
- package/dist/cjs/providers/mockProvider.d.ts +19 -0
- package/dist/cjs/providers/mockProvider.js +70 -0
- package/dist/cjs/providers/mockProvider.js.map +1 -0
- package/dist/cjs/utils/AddressUtils.d.ts +1 -0
- package/dist/cjs/utils/AddressUtils.js +14 -1
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/DepositUtils.d.ts +2 -1
- package/dist/cjs/utils/DepositUtils.js +9 -0
- package/dist/cjs/utils/DepositUtils.js.map +1 -1
- package/dist/cjs/utils/NetworkUtils.d.ts +1 -0
- package/dist/cjs/utils/NetworkUtils.js +6 -1
- package/dist/cjs/utils/NetworkUtils.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +213 -137
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +3 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +42 -1
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -1
- package/dist/esm/providers/index.d.ts +1 -0
- package/dist/esm/providers/index.js +2 -0
- package/dist/esm/providers/index.js.map +1 -1
- package/dist/esm/providers/mockProvider.d.ts +23 -0
- package/dist/esm/providers/mockProvider.js +73 -0
- package/dist/esm/providers/mockProvider.js.map +1 -0
- package/dist/esm/utils/AddressUtils.d.ts +1 -0
- package/dist/esm/utils/AddressUtils.js +16 -0
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/DepositUtils.d.ts +2 -1
- package/dist/esm/utils/DepositUtils.js +9 -0
- package/dist/esm/utils/DepositUtils.js.map +1 -1
- package/dist/esm/utils/NetworkUtils.d.ts +6 -0
- package/dist/esm/utils/NetworkUtils.js +10 -0
- package/dist/esm/utils/NetworkUtils.js.map +1 -1
- package/dist/esm/utils/SpokeUtils.js +1 -1
- package/dist/esm/utils/SpokeUtils.js.map +1 -1
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +1 -1
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -1
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +3 -1
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -1
- package/dist/types/providers/index.d.ts +1 -0
- package/dist/types/providers/index.d.ts.map +1 -1
- package/dist/types/providers/mockProvider.d.ts +24 -0
- package/dist/types/providers/mockProvider.d.ts.map +1 -0
- package/dist/types/utils/AddressUtils.d.ts +1 -0
- package/dist/types/utils/AddressUtils.d.ts.map +1 -1
- package/dist/types/utils/DepositUtils.d.ts +2 -1
- package/dist/types/utils/DepositUtils.d.ts.map +1 -1
- package/dist/types/utils/NetworkUtils.d.ts +6 -0
- package/dist/types/utils/NetworkUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/clients/BundleDataClient/BundleDataClient.ts +109 -57
- package/src/clients/BundleDataClient/utils/FillUtils.ts +47 -2
- package/src/providers/index.ts +1 -0
- package/src/providers/mockProvider.ts +77 -0
- package/src/utils/AddressUtils.ts +16 -0
- package/src/utils/DepositUtils.ts +9 -0
- package/src/utils/NetworkUtils.ts +11 -0
- package/src/utils/SpokeUtils.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BigNumber, providers } from "ethers";
|
|
2
|
+
import { Block, BlockTag, FeeData, TransactionResponse } from "@ethersproject/abstract-provider";
|
|
3
|
+
/**
|
|
4
|
+
* @notice Class used to test GasPriceOracle which makes ethers provider calls to the following implemented
|
|
5
|
+
* methods.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MockedProvider extends providers.StaticJsonRpcProvider {
|
|
8
|
+
readonly stdLastBaseFeePerGas: BigNumber;
|
|
9
|
+
readonly stdMaxPriorityFeePerGas: BigNumber;
|
|
10
|
+
readonly defaultChainId: number;
|
|
11
|
+
private transactions;
|
|
12
|
+
constructor(stdLastBaseFeePerGas: BigNumber, stdMaxPriorityFeePerGas: BigNumber, defaultChainId?: number);
|
|
13
|
+
getBlock(_blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<Block>;
|
|
14
|
+
send(method: string, _params: Array<any>): Promise<any>;
|
|
15
|
+
getFeeData(): Promise<FeeData>;
|
|
16
|
+
getTransaction(hash: string): Promise<TransactionResponse>;
|
|
17
|
+
getGasPrice(): Promise<BigNumber>;
|
|
18
|
+
getNetwork(): Promise<{
|
|
19
|
+
chainId: number;
|
|
20
|
+
name: string;
|
|
21
|
+
}>;
|
|
22
|
+
_setTransaction(hash: string, transaction: TransactionResponse): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=mockProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/mockProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGjG;;;GAGG;AACH,qBAAa,cAAe,SAAQ,SAAS,CAAC,qBAAqB;IAI/D,QAAQ,CAAC,oBAAoB,EAAE,SAAS;IACxC,QAAQ,CAAC,uBAAuB,EAAE,SAAS;IAC3C,QAAQ,CAAC,cAAc;IALzB,OAAO,CAAC,YAAY,CAA+C;gBAGxD,oBAAoB,EAAE,SAAS,EAC/B,uBAAuB,EAAE,SAAS,EAClC,cAAc,SAAI;IAK7B,QAAQ,CAAC,oBAAoB,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAoB9F,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IASvD,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAU9B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI1D,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC;IAIjC,UAAU,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAOxD,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB;CAG/D"}
|
|
@@ -8,4 +8,5 @@ import { providers } from "ethers";
|
|
|
8
8
|
export declare function isContractDeployedToAddress(address: string, provider: providers.Provider): Promise<boolean>;
|
|
9
9
|
export declare function compareAddresses(addressA: string, addressB: string): 1 | -1 | 0;
|
|
10
10
|
export declare function compareAddressesSimple(addressA?: string, addressB?: string): boolean;
|
|
11
|
+
export declare function isValidEvmAddress(address: string): boolean;
|
|
11
12
|
//# sourceMappingURL=AddressUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddressUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/AddressUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAS,MAAM,QAAQ,CAAC;AAG1C;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CASjH;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAY/E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAKpF"}
|
|
1
|
+
{"version":3,"file":"AddressUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/AddressUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAS,MAAM,QAAQ,CAAC;AAG1C;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CASjH;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAY/E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAKpF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc1D"}
|
|
@@ -3,7 +3,8 @@ import { CachingMechanismInterface, Deposit, DepositWithBlock, Fill, SlowFillReq
|
|
|
3
3
|
export declare enum InvalidFill {
|
|
4
4
|
DepositIdInvalid = 0,
|
|
5
5
|
DepositIdNotFound = 1,
|
|
6
|
-
FillMismatch = 2
|
|
6
|
+
FillMismatch = 2,
|
|
7
|
+
DepositIdOutOfRange = 3
|
|
7
8
|
}
|
|
8
9
|
export type DepositSearchResult = {
|
|
9
10
|
found: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DepositUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/DepositUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"DepositUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/DepositUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAa5G,oBAAY,WAAW;IACrB,gBAAgB,IAAI;IACpB,iBAAiB,IAAA;IACjB,YAAY,IAAA;IACZ,mBAAmB,IAAA;CACpB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,wBAAsB,6BAA6B,CACjD,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,IAAI,GAAG,eAAe,EAC5B,KAAK,CAAC,EAAE,yBAAyB,GAChC,OAAO,CAAC,mBAAmB,CAAC,CA2F9B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC,GAAG,OAAO,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAgB,GAAG,OAAO,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI9D"}
|
|
@@ -76,6 +76,12 @@ export declare function chainIsLinea(chainId: number): boolean;
|
|
|
76
76
|
* @returns True if chain corresponding to chainId has a hub pool implementation.
|
|
77
77
|
*/
|
|
78
78
|
export declare function chainIsL1(chainId: number): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Determines whether a chain ID runs on an EVM-like execution layer.
|
|
81
|
+
* @param chainId Chain ID to evaluate.
|
|
82
|
+
* @returns True if chain corresponding to chainId has an EVM-like execution layer.
|
|
83
|
+
*/
|
|
84
|
+
export declare function chainIsEvm(chainId: number): boolean;
|
|
79
85
|
/**
|
|
80
86
|
* Determines whether a chain ID has the capacity for having its USDC bridged via CCTP.
|
|
81
87
|
* @param chainId Chain ID to evaluate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/NetworkUtils.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAErE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa3D;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpD"}
|
|
1
|
+
{"version":3,"file":"NetworkUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/NetworkUtils.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAErE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAInD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa3D;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpD"}
|
package/package.json
CHANGED
|
@@ -30,8 +30,11 @@ import {
|
|
|
30
30
|
getImpliedBundleBlockRanges,
|
|
31
31
|
isSlowFill,
|
|
32
32
|
mapAsync,
|
|
33
|
+
filterAsync,
|
|
33
34
|
bnUint32Max,
|
|
34
35
|
isZeroValueDeposit,
|
|
36
|
+
chainIsEvm,
|
|
37
|
+
isValidEvmAddress,
|
|
35
38
|
} from "../../utils";
|
|
36
39
|
import winston from "winston";
|
|
37
40
|
import {
|
|
@@ -46,6 +49,7 @@ import {
|
|
|
46
49
|
prettyPrintV3SpokePoolEvents,
|
|
47
50
|
V3DepositWithBlock,
|
|
48
51
|
V3FillWithBlock,
|
|
52
|
+
verifyFillRepayment,
|
|
49
53
|
} from "./utils";
|
|
50
54
|
|
|
51
55
|
// max(uint256) - 1
|
|
@@ -55,6 +59,10 @@ type DataCache = Record<string, Promise<LoadDataReturnValue>>;
|
|
|
55
59
|
|
|
56
60
|
// V3 dictionary helper functions
|
|
57
61
|
function updateExpiredDepositsV3(dict: ExpiredDepositsToRefundV3, deposit: V3DepositWithBlock): void {
|
|
62
|
+
// A deposit refund for a deposit is invalid if the depositor has a bytes32 address input for an EVM chain. It is valid otherwise.
|
|
63
|
+
if (chainIsEvm(deposit.originChainId) && !isValidEvmAddress(deposit.depositor)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
58
66
|
const { originChainId, inputToken } = deposit;
|
|
59
67
|
if (!dict?.[originChainId]?.[inputToken]) {
|
|
60
68
|
assign(dict, [originChainId, inputToken], []);
|
|
@@ -75,8 +83,13 @@ function updateBundleFillsV3(
|
|
|
75
83
|
fill: V3FillWithBlock,
|
|
76
84
|
lpFeePct: BigNumber,
|
|
77
85
|
repaymentChainId: number,
|
|
78
|
-
repaymentToken: string
|
|
86
|
+
repaymentToken: string,
|
|
87
|
+
repaymentAddress: string
|
|
79
88
|
): void {
|
|
89
|
+
// It is impossible to refund a deposit if the repayment chain is EVM and the relayer is a non-evm address.
|
|
90
|
+
if (chainIsEvm(repaymentChainId) && !isValidEvmAddress(repaymentAddress)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
80
93
|
if (!dict?.[repaymentChainId]?.[repaymentToken]) {
|
|
81
94
|
assign(dict, [repaymentChainId, repaymentToken], {
|
|
82
95
|
fills: [],
|
|
@@ -86,19 +99,19 @@ function updateBundleFillsV3(
|
|
|
86
99
|
});
|
|
87
100
|
}
|
|
88
101
|
|
|
89
|
-
const bundleFill: BundleFillV3 = { ...fill, lpFeePct };
|
|
102
|
+
const bundleFill: BundleFillV3 = { ...fill, lpFeePct, relayer: repaymentAddress };
|
|
90
103
|
|
|
91
104
|
// Add all fills, slow and fast, to dictionary.
|
|
92
105
|
assign(dict, [repaymentChainId, repaymentToken, "fills"], [bundleFill]);
|
|
93
106
|
|
|
94
107
|
// All fills update the bundle LP fees.
|
|
95
108
|
const refundObj = dict[repaymentChainId][repaymentToken];
|
|
96
|
-
const realizedLpFee =
|
|
109
|
+
const realizedLpFee = bundleFill.inputAmount.mul(bundleFill.lpFeePct).div(fixedPointAdjustment);
|
|
97
110
|
refundObj.realizedLpFees = refundObj.realizedLpFees ? refundObj.realizedLpFees.add(realizedLpFee) : realizedLpFee;
|
|
98
111
|
|
|
99
112
|
// Only fast fills get refunded.
|
|
100
|
-
if (!isSlowFill(
|
|
101
|
-
const refundAmount =
|
|
113
|
+
if (!isSlowFill(bundleFill)) {
|
|
114
|
+
const refundAmount = bundleFill.inputAmount.mul(fixedPointAdjustment.sub(lpFeePct)).div(fixedPointAdjustment);
|
|
102
115
|
refundObj.totalRefundAmount = refundObj.totalRefundAmount
|
|
103
116
|
? refundObj.totalRefundAmount.add(refundAmount)
|
|
104
117
|
: refundAmount;
|
|
@@ -106,10 +119,10 @@ function updateBundleFillsV3(
|
|
|
106
119
|
// Instantiate dictionary if it doesn't exist.
|
|
107
120
|
refundObj.refunds ??= {};
|
|
108
121
|
|
|
109
|
-
if (refundObj.refunds[
|
|
110
|
-
refundObj.refunds[
|
|
122
|
+
if (refundObj.refunds[bundleFill.relayer]) {
|
|
123
|
+
refundObj.refunds[bundleFill.relayer] = refundObj.refunds[bundleFill.relayer].add(refundAmount);
|
|
111
124
|
} else {
|
|
112
|
-
refundObj.refunds[
|
|
125
|
+
refundObj.refunds[bundleFill.relayer] = refundAmount;
|
|
113
126
|
}
|
|
114
127
|
}
|
|
115
128
|
}
|
|
@@ -277,7 +290,7 @@ export class BundleDataClient {
|
|
|
277
290
|
// so as not to affect this approximate refund count.
|
|
278
291
|
const arweaveData = await this.loadArweaveData(bundleEvaluationBlockRanges);
|
|
279
292
|
if (arweaveData === undefined) {
|
|
280
|
-
combinedRefunds = this.getApproximateRefundsForBlockRange(chainIds, bundleEvaluationBlockRanges);
|
|
293
|
+
combinedRefunds = await this.getApproximateRefundsForBlockRange(chainIds, bundleEvaluationBlockRanges);
|
|
281
294
|
} else {
|
|
282
295
|
const { bundleFillsV3, expiredDepositsToRefundV3 } = arweaveData;
|
|
283
296
|
combinedRefunds = getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3);
|
|
@@ -298,50 +311,63 @@ export class BundleDataClient {
|
|
|
298
311
|
}
|
|
299
312
|
|
|
300
313
|
// @dev This helper function should probably be moved to the InventoryClient
|
|
301
|
-
getApproximateRefundsForBlockRange(chainIds: number[], blockRanges: number[][]): CombinedRefunds {
|
|
314
|
+
async getApproximateRefundsForBlockRange(chainIds: number[], blockRanges: number[][]): Promise<CombinedRefunds> {
|
|
302
315
|
const refundsForChain: CombinedRefunds = {};
|
|
303
316
|
for (const chainId of chainIds) {
|
|
304
317
|
if (this.spokePoolClients[chainId] === undefined) {
|
|
305
318
|
continue;
|
|
306
319
|
}
|
|
307
320
|
const chainIndex = chainIds.indexOf(chainId);
|
|
308
|
-
this.spokePoolClients[chainId]
|
|
309
|
-
.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
321
|
+
const fillsToCount = await filterAsync(this.spokePoolClients[chainId].getFills(), async (fill) => {
|
|
322
|
+
if (fill.blockNumber < blockRanges[chainIndex][0] || fill.blockNumber > blockRanges[chainIndex][1]) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
314
325
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
.forEach((fill) => {
|
|
326
|
-
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
327
|
-
assert(isDefined(matchingDeposit), "Deposit not found for fill.");
|
|
328
|
-
const { chainToSendRefundTo, repaymentToken } = getRefundInformationFromFill(
|
|
326
|
+
// If origin spoke pool client isn't defined, we can't validate it.
|
|
327
|
+
if (this.spokePoolClients[fill.originChainId] === undefined) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
331
|
+
const hasMatchingDeposit =
|
|
332
|
+
matchingDeposit !== undefined &&
|
|
333
|
+
this.getRelayHashFromEvent(fill) === this.getRelayHashFromEvent(matchingDeposit);
|
|
334
|
+
if (hasMatchingDeposit) {
|
|
335
|
+
const validRepayment = await verifyFillRepayment(
|
|
329
336
|
fill,
|
|
330
|
-
this.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
337
|
+
this.spokePoolClients[fill.destinationChainId].spokePool.provider,
|
|
338
|
+
matchingDeposit,
|
|
339
|
+
// @dev: to get valid repayment chain ID's, get all chain IDs for the bundle block range and remove
|
|
340
|
+
// disabled block ranges.
|
|
341
|
+
this.clients.configStoreClient
|
|
342
|
+
.getChainIdIndicesForBlock(blockRanges[0][1])
|
|
343
|
+
.filter((_chainId, i) => !isChainDisabled(blockRanges[i]))
|
|
334
344
|
);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
+
if (!isDefined(validRepayment)) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return hasMatchingDeposit;
|
|
350
|
+
});
|
|
351
|
+
fillsToCount.forEach((fill) => {
|
|
352
|
+
const matchingDeposit = this.spokePoolClients[fill.originChainId].getDeposit(fill.depositId);
|
|
353
|
+
assert(isDefined(matchingDeposit), "Deposit not found for fill.");
|
|
354
|
+
const { chainToSendRefundTo, repaymentToken } = getRefundInformationFromFill(
|
|
355
|
+
fill,
|
|
356
|
+
this.clients.hubPoolClient,
|
|
357
|
+
blockRanges,
|
|
358
|
+
this.chainIdListForBundleEvaluationBlockNumbers,
|
|
359
|
+
matchingDeposit!.fromLiteChain // Use ! because we've already asserted that matchingDeposit is defined.
|
|
360
|
+
);
|
|
361
|
+
// Assume that lp fees are 0 for the sake of speed. In the future we could batch compute
|
|
362
|
+
// these or make hardcoded assumptions based on the origin-repayment chain direction. This might result
|
|
363
|
+
// in slight over estimations of refunds, but its not clear whether underestimating or overestimating is
|
|
364
|
+
// worst from the relayer's perspective.
|
|
365
|
+
const { relayer, inputAmount: refundAmount } = fill;
|
|
366
|
+
refundsForChain[chainToSendRefundTo] ??= {};
|
|
367
|
+
refundsForChain[chainToSendRefundTo][repaymentToken] ??= {};
|
|
368
|
+
const existingRefundAmount = refundsForChain[chainToSendRefundTo][repaymentToken][relayer] ?? bnZero;
|
|
369
|
+
refundsForChain[chainToSendRefundTo][repaymentToken][relayer] = existingRefundAmount.add(refundAmount);
|
|
370
|
+
});
|
|
345
371
|
}
|
|
346
372
|
return refundsForChain;
|
|
347
373
|
}
|
|
@@ -468,7 +494,7 @@ export class BundleDataClient {
|
|
|
468
494
|
// ok for this use case.
|
|
469
495
|
const arweaveData = await this.loadArweaveData(pendingBundleBlockRanges);
|
|
470
496
|
if (arweaveData === undefined) {
|
|
471
|
-
combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, pendingBundleBlockRanges));
|
|
497
|
+
combinedRefunds.push(await this.getApproximateRefundsForBlockRange(chainIds, pendingBundleBlockRanges));
|
|
472
498
|
} else {
|
|
473
499
|
const { bundleFillsV3, expiredDepositsToRefundV3 } = arweaveData;
|
|
474
500
|
combinedRefunds.push(getRefundsFromBundle(bundleFillsV3, expiredDepositsToRefundV3));
|
|
@@ -483,7 +509,7 @@ export class BundleDataClient {
|
|
|
483
509
|
// - Only look up fills sent after the pending bundle's end blocks
|
|
484
510
|
// - Skip LP fee computations and just assume the relayer is being refunded the full deposit.inputAmount
|
|
485
511
|
const start = performance.now();
|
|
486
|
-
combinedRefunds.push(this.getApproximateRefundsForBlockRange(chainIds, widestBundleBlockRanges));
|
|
512
|
+
combinedRefunds.push(await this.getApproximateRefundsForBlockRange(chainIds, widestBundleBlockRanges));
|
|
487
513
|
this.logger.debug({
|
|
488
514
|
at: "BundleDataClient#getNextBundleRefunds",
|
|
489
515
|
message: `Loading approximate refunds for next bundle in ${Math.round(performance.now() - start) / 1000}s.`,
|
|
@@ -807,6 +833,8 @@ export class BundleDataClient {
|
|
|
807
833
|
|
|
808
834
|
// If deposit block is within origin chain bundle block range, then save as bundle deposit.
|
|
809
835
|
// If deposit is in bundle and it has expired, additionally save it as an expired deposit.
|
|
836
|
+
// Note: if the `depositor` field in the expired deposit is an invalid address, e.g. a bytes32 address on an EVM
|
|
837
|
+
// chain, then the deposit refund is invalid and ignored.
|
|
810
838
|
// If deposit is not in the bundle block range, then save it as an older deposit that
|
|
811
839
|
// may have expired.
|
|
812
840
|
if (deposit.blockNumber >= originChainBlockRange[0] && deposit.blockNumber <= originChainBlockRange[1]) {
|
|
@@ -856,16 +884,28 @@ export class BundleDataClient {
|
|
|
856
884
|
// tokens to the filler. We can't remove non-empty message deposit here in case there is a slow fill
|
|
857
885
|
// request for the deposit, we'd want to see the fill took place.
|
|
858
886
|
.filter((fill) => fill.blockNumber <= destinationChainBlockRange[1] && !isZeroValueDeposit(fill)),
|
|
859
|
-
async (
|
|
860
|
-
const relayDataHash = this.getRelayHashFromEvent(fill);
|
|
887
|
+
async (_fill) => {
|
|
861
888
|
fillCounter++;
|
|
862
|
-
|
|
889
|
+
const relayDataHash = this.getRelayHashFromEvent(_fill);
|
|
863
890
|
if (v3RelayHashes[relayDataHash]) {
|
|
864
891
|
if (!v3RelayHashes[relayDataHash].fill) {
|
|
865
892
|
assert(
|
|
866
893
|
isDefined(v3RelayHashes[relayDataHash].deposit),
|
|
867
894
|
"Deposit should exist in relay hash dictionary."
|
|
868
895
|
);
|
|
896
|
+
// `fill` will only possibly differ from `_fill` in the `relayer` field, which does not affect the
|
|
897
|
+
// relay hash, so it is safe to modify.
|
|
898
|
+
const fill = await verifyFillRepayment(
|
|
899
|
+
_fill,
|
|
900
|
+
destinationClient.spokePool.provider,
|
|
901
|
+
v3RelayHashes[relayDataHash].deposit!,
|
|
902
|
+
allChainIds
|
|
903
|
+
);
|
|
904
|
+
if (!isDefined(fill)) {
|
|
905
|
+
bundleInvalidFillsV3.push(_fill);
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
|
|
869
909
|
// At this point, the v3RelayHashes entry already existed meaning that there is a matching deposit,
|
|
870
910
|
// so this fill is validated.
|
|
871
911
|
v3RelayHashes[relayDataHash].fill = fill;
|
|
@@ -891,10 +931,10 @@ export class BundleDataClient {
|
|
|
891
931
|
}
|
|
892
932
|
|
|
893
933
|
// At this point, there is no relay hash dictionary entry for this fill, so we need to
|
|
894
|
-
// instantiate the entry.
|
|
934
|
+
// instantiate the entry. We won't modify the fill.relayer until we match it with a deposit.
|
|
895
935
|
v3RelayHashes[relayDataHash] = {
|
|
896
936
|
deposit: undefined,
|
|
897
|
-
fill:
|
|
937
|
+
fill: _fill,
|
|
898
938
|
slowFillRequest: undefined,
|
|
899
939
|
};
|
|
900
940
|
|
|
@@ -906,22 +946,34 @@ export class BundleDataClient {
|
|
|
906
946
|
// older deposit in case the spoke pool client's lookback isn't old enough to find the matching deposit.
|
|
907
947
|
// We can skip this step if the fill's fill deadline is not infinite, because we can assume that the
|
|
908
948
|
// spoke pool clients have loaded deposits old enough to cover all fills with a non-infinite fill deadline.
|
|
909
|
-
if (
|
|
949
|
+
if (_fill.blockNumber >= destinationChainBlockRange[0]) {
|
|
910
950
|
// Fill has a non-infinite expiry, and we can assume our spoke pool clients have old enough deposits
|
|
911
951
|
// to conclude that this fill is invalid if we haven't found a matching deposit in memory, so
|
|
912
952
|
// skip the historical query.
|
|
913
|
-
if (!INFINITE_FILL_DEADLINE.eq(
|
|
914
|
-
bundleInvalidFillsV3.push(
|
|
953
|
+
if (!INFINITE_FILL_DEADLINE.eq(_fill.fillDeadline)) {
|
|
954
|
+
bundleInvalidFillsV3.push(_fill);
|
|
915
955
|
return;
|
|
916
956
|
}
|
|
917
957
|
// If deposit is using the deterministic relay hash feature, then the following binary search-based
|
|
918
958
|
// algorithm will not work. However, it is impossible to emit an infinite fill deadline using
|
|
919
959
|
// the unsafeDepositV3 function so there is no need to catch the special case.
|
|
920
|
-
const historicalDeposit = await queryHistoricalDepositForFill(originClient,
|
|
960
|
+
const historicalDeposit = await queryHistoricalDepositForFill(originClient, _fill);
|
|
921
961
|
if (!historicalDeposit.found) {
|
|
922
|
-
bundleInvalidFillsV3.push(
|
|
962
|
+
bundleInvalidFillsV3.push(_fill);
|
|
923
963
|
} else {
|
|
924
964
|
const matchedDeposit = historicalDeposit.deposit;
|
|
965
|
+
const fill = await verifyFillRepayment(
|
|
966
|
+
_fill,
|
|
967
|
+
destinationClient.spokePool.provider,
|
|
968
|
+
matchedDeposit,
|
|
969
|
+
allChainIds
|
|
970
|
+
);
|
|
971
|
+
if (!isDefined(fill)) {
|
|
972
|
+
bundleInvalidFillsV3.push(_fill);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
v3RelayHashes[relayDataHash].fill = fill;
|
|
976
|
+
|
|
925
977
|
// @dev Since queryHistoricalDepositForFill validates the fill by checking individual
|
|
926
978
|
// object property values against the deposit's, we
|
|
927
979
|
// sanity check it here by comparing the full relay hashes. If there's an error here then the
|
|
@@ -1262,7 +1314,7 @@ export class BundleDataClient {
|
|
|
1262
1314
|
chainIds,
|
|
1263
1315
|
associatedDeposit!.fromLiteChain
|
|
1264
1316
|
);
|
|
1265
|
-
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken);
|
|
1317
|
+
updateBundleFillsV3(bundleFillsV3, fill, realizedLpFeePct, chainToSendRefundTo, repaymentToken, fill.relayer);
|
|
1266
1318
|
});
|
|
1267
1319
|
v3SlowFillLpFees.forEach(({ realizedLpFeePct: lpFeePct }, idx) => {
|
|
1268
1320
|
const deposit = validatedBundleSlowFills[idx];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
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";
|
|
3
5
|
import { HubPoolClient } from "../../HubPoolClient";
|
|
4
6
|
|
|
5
7
|
export function getRefundInformationFromFill(
|
|
@@ -44,3 +46,46 @@ export function getRefundInformationFromFill(
|
|
|
44
46
|
repaymentToken,
|
|
45
47
|
};
|
|
46
48
|
}
|
|
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
|
+
}
|
package/src/providers/index.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -38,3 +38,19 @@ export function compareAddressesSimple(addressA?: string, addressB?: string): bo
|
|
|
38
38
|
}
|
|
39
39
|
return addressA.toLowerCase() === addressB.toLowerCase();
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
export function isValidEvmAddress(address: string): boolean {
|
|
43
|
+
if (utils.isAddress(address)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
// We may throw an error here if hexZeroPadFails. This will happen if the address to pad is greater than 20 bytes long, indicating
|
|
47
|
+
// that the address had less than 12 leading zero bytes.
|
|
48
|
+
// We may also throw at getAddress if the input cannot be converted into a checksummed EVM address for some reason.
|
|
49
|
+
// For both cases, this indicates that the address cannot be casted as a bytes20 EVM address, so we should return false.
|
|
50
|
+
try {
|
|
51
|
+
const evmAddress = utils.hexZeroPad(utils.hexStripZeros(address), 20);
|
|
52
|
+
return utils.isAddress(utils.getAddress(evmAddress));
|
|
53
|
+
} catch (_e) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -5,6 +5,7 @@ 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";
|
|
8
9
|
import { getCurrentTime } from "./TimeUtils";
|
|
9
10
|
import { isDefined } from "./TypeGuards";
|
|
10
11
|
import { isDepositFormedCorrectly } from "./ValidatorUtils";
|
|
@@ -17,6 +18,7 @@ export enum InvalidFill {
|
|
|
17
18
|
DepositIdInvalid = 0, // Deposit ID seems invalid for origin SpokePool
|
|
18
19
|
DepositIdNotFound, // Deposit ID not found (bad RPC data?)
|
|
19
20
|
FillMismatch, // Fill does not match deposit parameters for deposit ID.
|
|
21
|
+
DepositIdOutOfRange, // Fill is for a deterministic deposit.
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export type DepositSearchResult =
|
|
@@ -40,6 +42,13 @@ export async function queryHistoricalDepositForFill(
|
|
|
40
42
|
fill: Fill | SlowFillRequest,
|
|
41
43
|
cache?: CachingMechanismInterface
|
|
42
44
|
): 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
|
+
}
|
|
43
52
|
if (fill.originChainId !== spokePoolClient.chainId) {
|
|
44
53
|
throw new Error(`OriginChainId mismatch (${fill.originChainId} != ${spokePoolClient.chainId})`);
|
|
45
54
|
}
|
|
@@ -123,6 +123,17 @@ export function chainIsL1(chainId: number): boolean {
|
|
|
123
123
|
return [CHAIN_IDs.MAINNET, CHAIN_IDs.SEPOLIA].includes(chainId);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Determines whether a chain ID runs on an EVM-like execution layer.
|
|
128
|
+
* @param chainId Chain ID to evaluate.
|
|
129
|
+
* @returns True if chain corresponding to chainId has an EVM-like execution layer.
|
|
130
|
+
*/
|
|
131
|
+
export function chainIsEvm(chainId: number): boolean {
|
|
132
|
+
chainId;
|
|
133
|
+
// TODO: Fix when we support non-EVM chains.
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
126
137
|
/**
|
|
127
138
|
* Determines whether a chain ID has the capacity for having its USDC bridged via CCTP.
|
|
128
139
|
* @param chainId Chain ID to evaluate.
|
package/src/utils/SpokeUtils.ts
CHANGED
|
@@ -208,7 +208,7 @@ export async function getBlockRangeForDepositId(
|
|
|
208
208
|
export async function getDepositIdAtBlock(contract: Contract, blockTag: number): Promise<BigNumber> {
|
|
209
209
|
const _depositIdAtBlock = await contract.numberOfDeposits({ blockTag });
|
|
210
210
|
const depositIdAtBlock = toBN(_depositIdAtBlock);
|
|
211
|
-
// Sanity check to ensure that the deposit ID is
|
|
211
|
+
// Sanity check to ensure that the deposit ID is greater than or equal to zero.
|
|
212
212
|
if (depositIdAtBlock.lt(bnZero)) {
|
|
213
213
|
throw new Error("Invalid deposit count");
|
|
214
214
|
}
|