@oydual31/more-vaults-sdk 0.3.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ethers/index.cjs +1794 -315
- package/dist/ethers/index.cjs.map +1 -1
- package/dist/ethers/index.d.cts +1147 -1
- package/dist/ethers/index.d.ts +1147 -1
- package/dist/ethers/index.js +1752 -317
- package/dist/ethers/index.js.map +1 -1
- package/dist/react/index.cjs +644 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +111 -2
- package/dist/react/index.d.ts +111 -2
- package/dist/react/index.js +638 -3
- package/dist/react/index.js.map +1 -1
- package/dist/{spokeRoutes-BIafSbQ3.d.cts → spokeRoutes-B8Lnk-t4.d.cts} +191 -2
- package/dist/{spokeRoutes-BIafSbQ3.d.ts → spokeRoutes-B8Lnk-t4.d.ts} +191 -2
- package/dist/viem/index.d.cts +4 -192
- package/dist/viem/index.d.ts +4 -192
- package/package.json +1 -1
- package/src/ethers/abis.ts +92 -0
- package/src/ethers/chains.ts +191 -0
- package/src/ethers/crossChainFlows.ts +208 -0
- package/src/ethers/curatorMulticall.ts +195 -0
- package/src/ethers/curatorStatus.ts +319 -0
- package/src/ethers/curatorSwaps.ts +192 -0
- package/src/ethers/distribution.ts +156 -0
- package/src/ethers/index.ts +96 -1
- package/src/ethers/preflight.ts +225 -1
- package/src/ethers/redeemFlows.ts +160 -1
- package/src/ethers/spokeRoutes.ts +361 -0
- package/src/ethers/topology.ts +240 -0
- package/src/ethers/types.ts +95 -0
- package/src/ethers/userHelpers.ts +193 -0
- package/src/ethers/utils.ts +28 -0
- package/src/react/index.ts +25 -0
- package/src/react/useCuratorVaultStatus.ts +32 -0
- package/src/react/useExecuteActions.ts +23 -0
- package/src/react/useIsCurator.ts +30 -0
- package/src/react/usePendingActions.ts +33 -0
- package/src/react/useProtocolWhitelist.ts +30 -0
- package/src/react/useSubmitActions.ts +27 -0
- package/src/react/useVaultAnalysis.ts +32 -0
- package/src/react/useVaultAssetBreakdown.ts +32 -0
- package/src/react/useVetoActions.ts +23 -0
package/dist/ethers/index.cjs
CHANGED
|
@@ -8,29 +8,356 @@ var CHAIN_IDS = {
|
|
|
8
8
|
flowEVMTestnet: 545,
|
|
9
9
|
arbitrum: 42161,
|
|
10
10
|
base: 8453,
|
|
11
|
-
ethereum: 1
|
|
11
|
+
ethereum: 1,
|
|
12
|
+
optimism: 10,
|
|
13
|
+
sonic: 146,
|
|
14
|
+
bsc: 56
|
|
12
15
|
};
|
|
13
16
|
var LZ_EIDS = {
|
|
14
17
|
flowMainnet: 30336,
|
|
15
18
|
flowTestnet: 30333,
|
|
16
19
|
arbitrum: 30110,
|
|
17
20
|
base: 30184,
|
|
18
|
-
ethereum: 30101
|
|
21
|
+
ethereum: 30101,
|
|
22
|
+
optimism: 30111,
|
|
23
|
+
sonic: 30332,
|
|
24
|
+
bsc: 30102
|
|
19
25
|
};
|
|
20
26
|
var EID_TO_CHAIN_ID = {
|
|
21
27
|
[LZ_EIDS.flowMainnet]: CHAIN_IDS.flowEVMMainnet,
|
|
22
28
|
[LZ_EIDS.flowTestnet]: CHAIN_IDS.flowEVMTestnet,
|
|
23
29
|
[LZ_EIDS.arbitrum]: CHAIN_IDS.arbitrum,
|
|
24
30
|
[LZ_EIDS.base]: CHAIN_IDS.base,
|
|
25
|
-
[LZ_EIDS.ethereum]: CHAIN_IDS.ethereum
|
|
31
|
+
[LZ_EIDS.ethereum]: CHAIN_IDS.ethereum,
|
|
32
|
+
[LZ_EIDS.optimism]: CHAIN_IDS.optimism,
|
|
33
|
+
[LZ_EIDS.sonic]: CHAIN_IDS.sonic,
|
|
34
|
+
[LZ_EIDS.bsc]: CHAIN_IDS.bsc
|
|
26
35
|
};
|
|
27
36
|
var CHAIN_ID_TO_EID = {
|
|
28
37
|
[CHAIN_IDS.flowEVMMainnet]: LZ_EIDS.flowMainnet,
|
|
29
38
|
[CHAIN_IDS.flowEVMTestnet]: LZ_EIDS.flowTestnet,
|
|
30
39
|
[CHAIN_IDS.arbitrum]: LZ_EIDS.arbitrum,
|
|
31
40
|
[CHAIN_IDS.base]: LZ_EIDS.base,
|
|
32
|
-
[CHAIN_IDS.ethereum]: LZ_EIDS.ethereum
|
|
41
|
+
[CHAIN_IDS.ethereum]: LZ_EIDS.ethereum,
|
|
42
|
+
[CHAIN_IDS.optimism]: LZ_EIDS.optimism,
|
|
43
|
+
[CHAIN_IDS.sonic]: LZ_EIDS.sonic,
|
|
44
|
+
[CHAIN_IDS.bsc]: LZ_EIDS.bsc
|
|
33
45
|
};
|
|
46
|
+
var OFT_ROUTES = {
|
|
47
|
+
/**
|
|
48
|
+
* stgUSDC — USDC bridged via Stargate v2.
|
|
49
|
+
* Underlying on Eth/Arb/Base/Op: native USDC. On Flow: stgUSDC (Stargate's wrapped USDC).
|
|
50
|
+
*/
|
|
51
|
+
stgUSDC: {
|
|
52
|
+
[
|
|
53
|
+
747
|
|
54
|
+
/* flowEVMMainnet */
|
|
55
|
+
]: { oft: "0xAF54BE5B6eEc24d6BFACf1cce4eaF680A8239398", token: "0xF1815bd50389c46847f0Bda824eC8da914045D14" },
|
|
56
|
+
[
|
|
57
|
+
1
|
|
58
|
+
/* ethereum */
|
|
59
|
+
]: { oft: "0xc026395860Db2d07ee33e05fE50ed7bD583189C7", token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
|
|
60
|
+
[
|
|
61
|
+
42161
|
|
62
|
+
/* arbitrum */
|
|
63
|
+
]: { oft: "0xe8CDF27AcD73a434D661C84887215F7598e7d0d3", token: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
|
|
64
|
+
[
|
|
65
|
+
8453
|
|
66
|
+
/* base */
|
|
67
|
+
]: { oft: "0x27a16dc786820B16E5c9028b75B99F6f604b5d26", token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
|
|
68
|
+
[
|
|
69
|
+
10
|
|
70
|
+
/* optimism */
|
|
71
|
+
]: { oft: "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", token: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" },
|
|
72
|
+
[
|
|
73
|
+
146
|
|
74
|
+
/* sonic */
|
|
75
|
+
]: { oft: "0xA272fFe20cFfe769CdFc4b63088DCD2C82a2D8F9", token: "0x29219dd400f2Bf60E5a23d13Be72B486D4038894" }
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* USDT — USDT bridged via Stargate v2.
|
|
79
|
+
*/
|
|
80
|
+
USDT: {
|
|
81
|
+
[
|
|
82
|
+
747
|
|
83
|
+
/* flowEVMMainnet */
|
|
84
|
+
]: { oft: "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6", token: "0x674843C06FF83502ddb4D37c2E09C01cdA38cbc8" },
|
|
85
|
+
[
|
|
86
|
+
1
|
|
87
|
+
/* ethereum */
|
|
88
|
+
]: { oft: "0x933597a323Eb81cAe705C5bC29985172fd5A3973", token: "0xdAC17F958D2ee523a2206206994597C13D831ec7" },
|
|
89
|
+
[
|
|
90
|
+
42161
|
|
91
|
+
/* arbitrum */
|
|
92
|
+
]: { oft: "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", token: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9" },
|
|
93
|
+
[
|
|
94
|
+
10
|
|
95
|
+
/* optimism */
|
|
96
|
+
]: { oft: "0x19cFCE47eD54a88614648DC3f19A5980097007dD", token: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58" }
|
|
97
|
+
},
|
|
98
|
+
/**
|
|
99
|
+
* USDF — USD Flow OFT. Bridges PYUSD (Ethereum) ↔ USDF (Flow EVM).
|
|
100
|
+
*/
|
|
101
|
+
USDF: {
|
|
102
|
+
[
|
|
103
|
+
747
|
|
104
|
+
/* flowEVMMainnet */
|
|
105
|
+
]: { oft: "0x2aabea2058b5ac2d339b163c6ab6f2b6d53aabed", token: "0x2aabea2058b5ac2d339b163c6ab6f2b6d53aabed" },
|
|
106
|
+
[
|
|
107
|
+
1
|
|
108
|
+
/* ethereum */
|
|
109
|
+
]: { oft: "0xfa0e06b54986ad96de87a8c56fea76fbd8d493f8", token: "0x6c3ea9036406852006290770BEdFcAbA0e23A0e8" }
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* PYUSD — PayPal USD bridged via OFTAdapter (Paxos / LayerZero).
|
|
113
|
+
*/
|
|
114
|
+
PYUSD: {
|
|
115
|
+
[
|
|
116
|
+
747
|
|
117
|
+
/* flowEVMMainnet */
|
|
118
|
+
]: { oft: "0x26d27d5AF2F6f1c14F40013C8619d97aaf015509", token: "0x99aF3EeA856556646C98c8B9b2548Fe815240750" },
|
|
119
|
+
[
|
|
120
|
+
42161
|
|
121
|
+
/* arbitrum */
|
|
122
|
+
]: { oft: "0x3CD2b89C49D130C08f1d683225b2e5DeB63ff876", token: "0x46850aD61C2B7d64d08c9C754F45254596696984" }
|
|
123
|
+
},
|
|
124
|
+
/**
|
|
125
|
+
* WFLOW — Wrapped FLOW NativeOFTAdapter (issued by Flow Foundation).
|
|
126
|
+
*/
|
|
127
|
+
WFLOW: {
|
|
128
|
+
[
|
|
129
|
+
747
|
|
130
|
+
/* flowEVMMainnet */
|
|
131
|
+
]: { oft: "0xd296588850bee2770136464ffdddd78c32f2a07c", token: "0xd296588850bee2770136464ffdddd78c32f2a07c" },
|
|
132
|
+
[
|
|
133
|
+
1
|
|
134
|
+
/* ethereum */
|
|
135
|
+
]: { oft: "0xc1b45896b5fc9422a8f779653808297bb4f546f9", token: "0x5c147e74D63B1D31AA3Fd78Eb229B65161983B2b" }
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* WETH — ETH OFT via Stargate v2. underlying = native ETH (no approval needed).
|
|
139
|
+
*/
|
|
140
|
+
WETH: {
|
|
141
|
+
[
|
|
142
|
+
747
|
|
143
|
+
/* flowEVMMainnet */
|
|
144
|
+
]: { oft: "0x45f1A95A4D3f3836523F5c83673c797f4d4d263B", token: "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590" },
|
|
145
|
+
[
|
|
146
|
+
1
|
|
147
|
+
/* ethereum */
|
|
148
|
+
]: { oft: "0x77b2043768d28E9C9aB44E1aBfC95944bcE57931", token: "0x0000000000000000000000000000000000000000" },
|
|
149
|
+
[
|
|
150
|
+
42161
|
|
151
|
+
/* arbitrum */
|
|
152
|
+
]: { oft: "0xA45B5130f36CDcA45667738e2a258AB09f4A5f7F", token: "0x0000000000000000000000000000000000000000" },
|
|
153
|
+
[
|
|
154
|
+
8453
|
|
155
|
+
/* base */
|
|
156
|
+
]: { oft: "0xdc181Bd607330aeeBEF6ea62e03e5e1Fb4B6F7C7", token: "0x0000000000000000000000000000000000000000" }
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* sUSDe — Ethena staked USDe (yield-bearing stablecoin).
|
|
160
|
+
*/
|
|
161
|
+
sUSDe: {
|
|
162
|
+
[
|
|
163
|
+
1
|
|
164
|
+
/* ethereum */
|
|
165
|
+
]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497" },
|
|
166
|
+
[
|
|
167
|
+
42161
|
|
168
|
+
/* arbitrum */
|
|
169
|
+
]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
|
|
170
|
+
[
|
|
171
|
+
8453
|
|
172
|
+
/* base */
|
|
173
|
+
]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
|
|
174
|
+
[
|
|
175
|
+
10
|
|
176
|
+
/* optimism */
|
|
177
|
+
]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" },
|
|
178
|
+
[
|
|
179
|
+
56
|
|
180
|
+
/* bsc */
|
|
181
|
+
]: { oft: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2", token: "0x211cc4dd073734da055fbf44a2b4667d5e5fe5d2" }
|
|
182
|
+
},
|
|
183
|
+
/**
|
|
184
|
+
* USDe — Ethena USD stablecoin.
|
|
185
|
+
*/
|
|
186
|
+
USDe: {
|
|
187
|
+
[
|
|
188
|
+
1
|
|
189
|
+
/* ethereum */
|
|
190
|
+
]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3" },
|
|
191
|
+
[
|
|
192
|
+
42161
|
|
193
|
+
/* arbitrum */
|
|
194
|
+
]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
|
|
195
|
+
[
|
|
196
|
+
8453
|
|
197
|
+
/* base */
|
|
198
|
+
]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
|
|
199
|
+
[
|
|
200
|
+
10
|
|
201
|
+
/* optimism */
|
|
202
|
+
]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" },
|
|
203
|
+
[
|
|
204
|
+
56
|
|
205
|
+
/* bsc */
|
|
206
|
+
]: { oft: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34", token: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" }
|
|
207
|
+
},
|
|
208
|
+
/**
|
|
209
|
+
* weETH — Ether.Fi liquid restaking token.
|
|
210
|
+
*/
|
|
211
|
+
weETH: {
|
|
212
|
+
[
|
|
213
|
+
1
|
|
214
|
+
/* ethereum */
|
|
215
|
+
]: { oft: "0xcd2eb13d6831d4602d80e5db9230a57596cdca63", token: "0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee" },
|
|
216
|
+
[
|
|
217
|
+
8453
|
|
218
|
+
/* base */
|
|
219
|
+
]: { oft: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a", token: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a" },
|
|
220
|
+
[
|
|
221
|
+
10
|
|
222
|
+
/* optimism */
|
|
223
|
+
]: { oft: "0x5a7facb970d094b6c7ff1df0ea68d99e6e73cbff", token: "0x5a7facb970d094b6c7ff1df0ea68d99e6e73cbff" },
|
|
224
|
+
[
|
|
225
|
+
56
|
|
226
|
+
/* bsc */
|
|
227
|
+
]: { oft: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a", token: "0x04c0599ae5a44757c0af6f9ec3b93da8976c150a" },
|
|
228
|
+
[
|
|
229
|
+
146
|
|
230
|
+
/* sonic */
|
|
231
|
+
]: { oft: "0xa3d68b74bf0528fdd07263c60d6488749044914b", token: "0xa3d68b74bf0528fdd07263c60d6488749044914b" }
|
|
232
|
+
},
|
|
233
|
+
/**
|
|
234
|
+
* rsETH — Kelp DAO liquid restaking token.
|
|
235
|
+
*/
|
|
236
|
+
rsETH: {
|
|
237
|
+
[
|
|
238
|
+
1
|
|
239
|
+
/* ethereum */
|
|
240
|
+
]: { oft: "0x85d456b2dff1fd8245387c0bfb64dfb700e98ef3", token: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7" },
|
|
241
|
+
[
|
|
242
|
+
42161
|
|
243
|
+
/* arbitrum */
|
|
244
|
+
]: { oft: "0x4186bfc76e2e237523cbc30fd220fe055156b41f", token: "0x4186bfc76e2e237523cbc30fd220fe055156b41f" },
|
|
245
|
+
[
|
|
246
|
+
8453
|
|
247
|
+
/* base */
|
|
248
|
+
]: { oft: "0x1bc71130a0e39942a7658878169764bbd8a45993", token: "0x1bc71130a0e39942a7658878169764bbd8a45993" },
|
|
249
|
+
[
|
|
250
|
+
10
|
|
251
|
+
/* optimism */
|
|
252
|
+
]: { oft: "0x4186bfc76e2e237523cbc30fd220fe055156b41f", token: "0x4186bfc76e2e237523cbc30fd220fe055156b41f" },
|
|
253
|
+
[
|
|
254
|
+
146
|
|
255
|
+
/* sonic */
|
|
256
|
+
]: { oft: "0xd75787ba9aba324420d522bda84c08c87e5099b1", token: "0xd75787ba9aba324420d522bda84c08c87e5099b1" }
|
|
257
|
+
},
|
|
258
|
+
/**
|
|
259
|
+
* rswETH — Swell Network liquid restaking token.
|
|
260
|
+
*/
|
|
261
|
+
rswETH: {
|
|
262
|
+
[
|
|
263
|
+
1
|
|
264
|
+
/* ethereum */
|
|
265
|
+
]: { oft: "0x1486d39646cdee84619bd05997319545a8575079", token: "0xFAe103DC9cf190eD75350761e95403b7b8aFa6c0" },
|
|
266
|
+
[
|
|
267
|
+
42161
|
|
268
|
+
/* arbitrum */
|
|
269
|
+
]: { oft: "0xb1fe27b32ffb5ce54e272c096547f1e86c19e72f", token: "0xb1fe27b32ffb5ce54e272c096547f1e86c19e72f" },
|
|
270
|
+
[
|
|
271
|
+
8453
|
|
272
|
+
/* base */
|
|
273
|
+
]: { oft: "0x850cdf416668210ed0c36bfff5d21921c7ada3b8", token: "0x850cdf416668210ed0c36bfff5d21921c7ada3b8" }
|
|
274
|
+
},
|
|
275
|
+
/**
|
|
276
|
+
* USR — Resolv Labs USD stablecoin.
|
|
277
|
+
*/
|
|
278
|
+
USR: {
|
|
279
|
+
[
|
|
280
|
+
1
|
|
281
|
+
/* ethereum */
|
|
282
|
+
]: { oft: "0xd2ee2776f34ef4e7325745b06e6d464b08d4be0e", token: "0x66a1E37c9b0eAddca17d3662D6c05F4DECf3e110" },
|
|
283
|
+
[
|
|
284
|
+
42161
|
|
285
|
+
/* arbitrum */
|
|
286
|
+
]: { oft: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9", token: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9" },
|
|
287
|
+
[
|
|
288
|
+
8453
|
|
289
|
+
/* base */
|
|
290
|
+
]: { oft: "0x35e5db674d8e93a03d814fa0ada70731efe8a4b9", token: "0x35e5db674d8e93a03d814fa0ada70731efe8a4b9" },
|
|
291
|
+
[
|
|
292
|
+
56
|
|
293
|
+
/* bsc */
|
|
294
|
+
]: { oft: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9", token: "0x2492d0006411af6c8bbb1c8afc1b0197350a79e9" }
|
|
295
|
+
},
|
|
296
|
+
/**
|
|
297
|
+
* wstUSR — Resolv Labs wrapped staked USR (yield-bearing).
|
|
298
|
+
*/
|
|
299
|
+
wstUSR: {
|
|
300
|
+
[
|
|
301
|
+
1
|
|
302
|
+
/* ethereum */
|
|
303
|
+
]: { oft: "0xab17c1fe647c37ceb9b96d1c27dd189bf8451978", token: "0x1202F5C7b4B9E47a1A484E8B270be34dbbC75055" },
|
|
304
|
+
[
|
|
305
|
+
42161
|
|
306
|
+
/* arbitrum */
|
|
307
|
+
]: { oft: "0x66cfbd79257dc5217903a36293120282548e2254", token: "0x66cfbd79257dc5217903a36293120282548e2254" },
|
|
308
|
+
[
|
|
309
|
+
8453
|
|
310
|
+
/* base */
|
|
311
|
+
]: { oft: "0xb67675158b412d53fe6b68946483ba920b135ba1", token: "0xb67675158b412d53fe6b68946483ba920b135ba1" },
|
|
312
|
+
[
|
|
313
|
+
56
|
|
314
|
+
/* bsc */
|
|
315
|
+
]: { oft: "0x4254813524695def4163a169e901f3d7a1a55429", token: "0x4254813524695def4163a169e901f3d7a1a55429" }
|
|
316
|
+
},
|
|
317
|
+
/**
|
|
318
|
+
* USDtb — Ethena treasury-backed stablecoin.
|
|
319
|
+
*/
|
|
320
|
+
USDtb: {
|
|
321
|
+
[
|
|
322
|
+
1
|
|
323
|
+
/* ethereum */
|
|
324
|
+
]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xC139190F447e929f090Edeb554D95AbB8b18aC1C" },
|
|
325
|
+
[
|
|
326
|
+
42161
|
|
327
|
+
/* arbitrum */
|
|
328
|
+
]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xc708b6887db46005da033501f8aebee72d191a5d" },
|
|
329
|
+
[
|
|
330
|
+
8453
|
|
331
|
+
/* base */
|
|
332
|
+
]: { oft: "0xc708b6887db46005da033501f8aebee72d191a5d", token: "0xc708b6887db46005da033501f8aebee72d191a5d" }
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
var UNISWAP_V3_ROUTERS = {
|
|
336
|
+
[8453]: "0x2626664c2603336E57B271c5C0b26F421741e481",
|
|
337
|
+
// Base — SwapRouter02 (no deadline)
|
|
338
|
+
[1]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
339
|
+
// Ethereum — SwapRouter
|
|
340
|
+
[42161]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
341
|
+
// Arbitrum — SwapRouter
|
|
342
|
+
[10]: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
|
|
343
|
+
// Optimism — SwapRouter
|
|
344
|
+
[747]: "0xeEDC6Ff75e1b10B903D9013c358e446a73d35341"
|
|
345
|
+
// Flow EVM — FlowSwap V3 SwapRouter
|
|
346
|
+
};
|
|
347
|
+
var PUBLIC_RPCS = {
|
|
348
|
+
1: ["https://ethereum-rpc.publicnode.com", "https://eth.drpc.org", "https://eth.llamarpc.com"],
|
|
349
|
+
10: ["https://mainnet.optimism.io", "https://optimism-rpc.publicnode.com"],
|
|
350
|
+
42161: ["https://arbitrum-one-rpc.publicnode.com", "https://arbitrum.publicnode.com"],
|
|
351
|
+
8453: ["https://base-rpc.publicnode.com", "https://base.llamarpc.com", "https://mainnet.base.org"],
|
|
352
|
+
747: ["https://mainnet.evm.nodes.onflow.org"],
|
|
353
|
+
146: ["https://rpc.soniclabs.com"],
|
|
354
|
+
56: ["https://bsc-dataseed1.binance.org", "https://bsc-dataseed2.binance.org"]
|
|
355
|
+
};
|
|
356
|
+
function createChainProvider(chainId) {
|
|
357
|
+
const rpcs = PUBLIC_RPCS[chainId];
|
|
358
|
+
if (!rpcs?.length) return null;
|
|
359
|
+
return new ethers.JsonRpcProvider(rpcs[0], chainId, { staticNetwork: true });
|
|
360
|
+
}
|
|
34
361
|
var LZ_TIMEOUTS = {
|
|
35
362
|
/** Poll interval between balance/event checks */
|
|
36
363
|
POLL_INTERVAL: 3e4,
|
|
@@ -134,6 +461,58 @@ var LZ_ENDPOINT_ABI = [
|
|
|
134
461
|
"function composeQueue(address from, address to, bytes32 guid, uint16 index) view returns (bytes32 messageHash)",
|
|
135
462
|
"function lzCompose(address _from, address _to, bytes32 _guid, uint16 _index, bytes _message, bytes _extraData) payable"
|
|
136
463
|
];
|
|
464
|
+
var MULTICALL_ABI = [
|
|
465
|
+
"function submitActions(bytes[] actionsData) returns (uint256 nonce)",
|
|
466
|
+
"function executeActions(uint256 actionsNonce)",
|
|
467
|
+
"function getPendingActions(uint256 actionsNonce) view returns (bytes[] actionsData, uint256 pendingUntil)",
|
|
468
|
+
"function getCurrentNonce() view returns (uint256)",
|
|
469
|
+
"function vetoActions(uint256[] actionsNonces)"
|
|
470
|
+
];
|
|
471
|
+
var DEX_ABI = [
|
|
472
|
+
"function executeSwap(tuple(address targetContract, address tokenIn, address tokenOut, uint256 maxAmountIn, uint256 minAmountOut, bytes swapCallData) params) returns (uint256 amountOut)",
|
|
473
|
+
"function executeBatchSwap(tuple(tuple(address targetContract, address tokenIn, address tokenOut, uint256 maxAmountIn, uint256 minAmountOut, bytes swapCallData)[] swaps) params) returns (uint256[] amountsOut)"
|
|
474
|
+
];
|
|
475
|
+
var BRIDGE_FACET_ABI = [
|
|
476
|
+
"function executeBridging(address adapter, address token, uint256 amount, bytes bridgeSpecificParams) payable",
|
|
477
|
+
"function initVaultActionRequest(uint8 actionType, bytes actionCallData, uint256 amountLimit, bytes extraOptions) payable returns (bytes32 guid)",
|
|
478
|
+
"function executeRequest(bytes32 guid)"
|
|
479
|
+
];
|
|
480
|
+
var ERC7540_FACET_ABI = [
|
|
481
|
+
"function erc7540RequestDeposit(address vault, uint256 assets) returns (uint256 requestId)",
|
|
482
|
+
"function erc7540RequestRedeem(address vault, uint256 shares) returns (uint256 requestId)",
|
|
483
|
+
"function erc7540Deposit(address vault, uint256 assets) returns (uint256 shares)",
|
|
484
|
+
"function erc7540Redeem(address vault, uint256 shares) returns (uint256 assets)"
|
|
485
|
+
];
|
|
486
|
+
var ERC4626_FACET_ABI = [
|
|
487
|
+
"function erc4626Deposit(address vault, uint256 assets) returns (uint256 shares)",
|
|
488
|
+
"function erc4626Redeem(address vault, uint256 shares) returns (uint256 assets)"
|
|
489
|
+
];
|
|
490
|
+
var CURATOR_CONFIG_ABI = [
|
|
491
|
+
"function curator() view returns (address)",
|
|
492
|
+
"function timeLockPeriod() view returns (uint256)",
|
|
493
|
+
"function getAvailableAssets() view returns (address[])",
|
|
494
|
+
"function getMaxSlippagePercent() view returns (uint256)",
|
|
495
|
+
"function getCrossChainAccountingManager() view returns (address)",
|
|
496
|
+
"function paused() view returns (bool)"
|
|
497
|
+
];
|
|
498
|
+
var LZ_ADAPTER_ABI = [
|
|
499
|
+
"function quoteBridgeFee(bytes bridgeSpecificParams) view returns (uint256 nativeFee)",
|
|
500
|
+
"function quoteReadFee(address[] vaults, uint32[] eids, bytes _extraOptions) view returns (tuple(uint256 nativeFee, uint256 lzTokenFee) fee)"
|
|
501
|
+
];
|
|
502
|
+
var VAULT_ANALYSIS_ABI = [
|
|
503
|
+
"function getAvailableAssets() view returns (address[])",
|
|
504
|
+
"function getDepositableAssets() view returns (address[])",
|
|
505
|
+
"function isAssetAvailable(address asset) view returns (bool)",
|
|
506
|
+
"function isAssetDepositable(address asset) view returns (bool)",
|
|
507
|
+
"function isDepositWhitelistEnabled() view returns (bool)",
|
|
508
|
+
"function getAvailableToDeposit(address depositor) view returns (uint256)",
|
|
509
|
+
"function moreVaultsRegistry() view returns (address)"
|
|
510
|
+
];
|
|
511
|
+
var REGISTRY_ABI = [
|
|
512
|
+
"function isWhitelisted(address protocol) view returns (bool)",
|
|
513
|
+
"function isBridgeAllowed(address bridge) view returns (bool)",
|
|
514
|
+
"function getAllowedFacets() view returns (address[])"
|
|
515
|
+
];
|
|
137
516
|
|
|
138
517
|
// src/ethers/errors.ts
|
|
139
518
|
var MoreVaultsError = class extends Error {
|
|
@@ -208,89 +587,9 @@ var WrongChainError = class extends MoreVaultsError {
|
|
|
208
587
|
this.name = "WrongChainError";
|
|
209
588
|
}
|
|
210
589
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
|
|
215
|
-
config.getCrossChainAccountingManager(),
|
|
216
|
-
config.getEscrow(),
|
|
217
|
-
config.isHub(),
|
|
218
|
-
bridge.oraclesCrossChainAccounting(),
|
|
219
|
-
config.paused()
|
|
220
|
-
]);
|
|
221
|
-
if (ccManager === ethers.ZeroAddress) {
|
|
222
|
-
throw new Error(
|
|
223
|
-
`[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
if (registeredEscrow === ethers.ZeroAddress) {
|
|
227
|
-
throw new Error(
|
|
228
|
-
`[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
if (!isHub) {
|
|
232
|
-
throw new Error(
|
|
233
|
-
`[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
if (oraclesEnabled) {
|
|
237
|
-
throw new Error(
|
|
238
|
-
`[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
if (isPaused) {
|
|
242
|
-
throw new Error(
|
|
243
|
-
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
async function preflightRedeemLiquidity(provider, vault, shares) {
|
|
248
|
-
const config = new ethers.Contract(vault, CONFIG_ABI, provider);
|
|
249
|
-
const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
|
|
250
|
-
const [isHub, oraclesEnabled] = await Promise.all([
|
|
251
|
-
config.isHub(),
|
|
252
|
-
bridge.oraclesCrossChainAccounting()
|
|
253
|
-
]);
|
|
254
|
-
if (!isHub || oraclesEnabled) return;
|
|
255
|
-
const vaultContract = new ethers.Contract(vault, VAULT_ABI, provider);
|
|
256
|
-
const underlying = await vaultContract.asset();
|
|
257
|
-
const underlyingContract = new ethers.Contract(underlying, ERC20_ABI, provider);
|
|
258
|
-
const [hubLiquid, assetsNeeded] = await Promise.all([
|
|
259
|
-
underlyingContract.balanceOf(vault),
|
|
260
|
-
vaultContract.convertToAssets(shares)
|
|
261
|
-
]);
|
|
262
|
-
if (hubLiquid < assetsNeeded) {
|
|
263
|
-
throw new InsufficientLiquidityError(vault, hubLiquid, assetsNeeded);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
async function preflightSync(provider, vault) {
|
|
267
|
-
const config = new ethers.Contract(vault, CONFIG_ABI, provider);
|
|
268
|
-
const [isPaused, depositCapResult] = await Promise.all([
|
|
269
|
-
config.paused(),
|
|
270
|
-
config.maxDeposit(ethers.ZeroAddress).catch(() => null)
|
|
271
|
-
]);
|
|
272
|
-
if (isPaused) {
|
|
273
|
-
throw new Error(
|
|
274
|
-
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
if (depositCapResult !== null && depositCapResult === 0n) {
|
|
278
|
-
throw new Error(
|
|
279
|
-
`[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// src/ethers/chainValidation.ts
|
|
285
|
-
async function validateWalletChain(signer, hubChainId) {
|
|
286
|
-
if (!hubChainId) return;
|
|
287
|
-
const network = await signer.provider?.getNetwork();
|
|
288
|
-
if (!network) return;
|
|
289
|
-
const current = Number(network.chainId);
|
|
290
|
-
if (current !== hubChainId) {
|
|
291
|
-
throw new WrongChainError(current, hubChainId);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
590
|
+
var STARGATE_TYPE_ABI = [
|
|
591
|
+
"function stargateType() view returns (uint8)"
|
|
592
|
+
];
|
|
294
593
|
var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
295
594
|
var MULTICALL3_ABI = [
|
|
296
595
|
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
|
|
@@ -470,8 +769,18 @@ async function getVaultStatus(provider, vault) {
|
|
|
470
769
|
issues
|
|
471
770
|
};
|
|
472
771
|
}
|
|
473
|
-
|
|
474
|
-
|
|
772
|
+
async function detectStargateOft(provider, oft) {
|
|
773
|
+
try {
|
|
774
|
+
const contract = new ethers.Contract(oft, STARGATE_TYPE_ABI, provider);
|
|
775
|
+
await contract.stargateType();
|
|
776
|
+
return true;
|
|
777
|
+
} catch {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
var LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
|
|
782
|
+
var EMPTY_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
783
|
+
var RECEIVED_HASH = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
475
784
|
async function ensureAllowance2(signer, token, spender, amount) {
|
|
476
785
|
const owner = await signer.getAddress();
|
|
477
786
|
const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
|
|
@@ -481,176 +790,34 @@ async function ensureAllowance2(signer, token, spender, amount) {
|
|
|
481
790
|
await tx.wait();
|
|
482
791
|
}
|
|
483
792
|
}
|
|
484
|
-
async function
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
await
|
|
488
|
-
const
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
});
|
|
500
|
-
if (parsed && parsed.name === "Transfer" && parsed.args[0] === "0x0000000000000000000000000000000000000000") {
|
|
501
|
-
shares = parsed.args[2];
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
} catch {
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return { receipt, shares };
|
|
508
|
-
}
|
|
509
|
-
async function depositMultiAsset(signer, addresses, tokens, amounts, receiver, minShares) {
|
|
510
|
-
await validateWalletChain(signer, addresses.hubChainId);
|
|
511
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
512
|
-
await ensureAllowance2(signer, tokens[i], addresses.vault, amounts[i]);
|
|
513
|
-
}
|
|
514
|
-
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
515
|
-
const tx = await vault["deposit(address[],uint256[],address,uint256)"](tokens, amounts, receiver, minShares);
|
|
516
|
-
const receipt = await tx.wait();
|
|
517
|
-
let shares = 0n;
|
|
518
|
-
for (const log of receipt.logs) {
|
|
519
|
-
try {
|
|
520
|
-
const parsed = vault.interface.parseLog({
|
|
521
|
-
topics: log.topics,
|
|
522
|
-
data: log.data
|
|
523
|
-
});
|
|
524
|
-
if (parsed && parsed.name === "Deposit") {
|
|
525
|
-
shares = parsed.args[4];
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
} catch {
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
return { receipt, shares };
|
|
532
|
-
}
|
|
533
|
-
var depositCrossChainOracleOn = depositSimple;
|
|
534
|
-
async function depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions = "0x") {
|
|
535
|
-
const provider = signer.provider;
|
|
536
|
-
const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
|
|
537
|
-
if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
|
|
538
|
-
await validateWalletChain(signer, addresses.hubChainId);
|
|
539
|
-
await preflightAsync(provider, addresses.vault);
|
|
540
|
-
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
541
|
-
const underlying = await vault.asset();
|
|
542
|
-
await ensureAllowance2(signer, underlying, escrow, assets);
|
|
793
|
+
async function depositFromSpoke(signer, spokeOFT, composer, hubEid, spokeEid, amount, receiver, lzFee, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
|
|
794
|
+
await ensureAllowance2(signer, spokeOFT, spokeOFT, amount);
|
|
795
|
+
const oft = new ethers.Contract(spokeOFT, OFT_ABI, signer);
|
|
796
|
+
const refundAddress = await signer.getAddress();
|
|
797
|
+
const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
798
|
+
const composerBytes32 = ethers.zeroPadValue(composer, 32);
|
|
799
|
+
const hopSendParam = {
|
|
800
|
+
dstEid: spokeEid,
|
|
801
|
+
to: receiverBytes32,
|
|
802
|
+
amountLD: 0n,
|
|
803
|
+
minAmountLD: minSharesOut,
|
|
804
|
+
extraOptions: "0x",
|
|
805
|
+
composeMsg: "0x",
|
|
806
|
+
oftCmd: "0x"
|
|
807
|
+
};
|
|
543
808
|
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
544
|
-
const
|
|
545
|
-
[
|
|
546
|
-
|
|
809
|
+
const composeMsg = coder.encode(
|
|
810
|
+
[
|
|
811
|
+
"tuple(uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd)",
|
|
812
|
+
"uint256"
|
|
813
|
+
],
|
|
814
|
+
[hopSendParam, minMsgValue]
|
|
547
815
|
);
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
extraOptions,
|
|
554
|
-
{ value: lzFee }
|
|
555
|
-
);
|
|
556
|
-
const tx = await bridge.initVaultActionRequest(
|
|
557
|
-
ActionType.DEPOSIT,
|
|
558
|
-
actionCallData,
|
|
559
|
-
0,
|
|
560
|
-
// amountLimit = 0 for deposits (minAmountOut handled by cross-chain manager)
|
|
561
|
-
extraOptions,
|
|
562
|
-
{ value: lzFee }
|
|
563
|
-
);
|
|
564
|
-
const receipt = await tx.wait();
|
|
565
|
-
return { receipt, guid };
|
|
566
|
-
}
|
|
567
|
-
async function mintAsync(signer, addresses, shares, maxAssets, receiver, lzFee, extraOptions = "0x") {
|
|
568
|
-
const provider = signer.provider;
|
|
569
|
-
const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
|
|
570
|
-
if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
|
|
571
|
-
await validateWalletChain(signer, addresses.hubChainId);
|
|
572
|
-
await preflightAsync(provider, addresses.vault);
|
|
573
|
-
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
574
|
-
const underlying = await vault.asset();
|
|
575
|
-
await ensureAllowance2(signer, underlying, escrow, maxAssets);
|
|
576
|
-
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
577
|
-
const actionCallData = coder.encode(
|
|
578
|
-
["uint256", "address"],
|
|
579
|
-
[shares, receiver]
|
|
580
|
-
);
|
|
581
|
-
const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
|
|
582
|
-
const guid = await bridge.initVaultActionRequest.staticCall(
|
|
583
|
-
ActionType.MINT,
|
|
584
|
-
actionCallData,
|
|
585
|
-
maxAssets,
|
|
586
|
-
extraOptions,
|
|
587
|
-
{ value: lzFee }
|
|
588
|
-
);
|
|
589
|
-
const tx = await bridge.initVaultActionRequest(
|
|
590
|
-
ActionType.MINT,
|
|
591
|
-
actionCallData,
|
|
592
|
-
maxAssets,
|
|
593
|
-
extraOptions,
|
|
594
|
-
{ value: lzFee }
|
|
595
|
-
);
|
|
596
|
-
const receipt = await tx.wait();
|
|
597
|
-
return { receipt, guid };
|
|
598
|
-
}
|
|
599
|
-
async function smartDeposit(signer, provider, addresses, assets, receiver, extraOptions = "0x") {
|
|
600
|
-
const vault = addresses.vault;
|
|
601
|
-
const status = await getVaultStatus(provider, vault);
|
|
602
|
-
if (status.mode === "paused") {
|
|
603
|
-
throw new VaultPausedError(vault);
|
|
604
|
-
}
|
|
605
|
-
if (status.mode === "full") {
|
|
606
|
-
throw new CapacityFullError(vault);
|
|
607
|
-
}
|
|
608
|
-
if (status.recommendedDepositFlow === "depositAsync") {
|
|
609
|
-
const lzFee = await quoteLzFee(provider, vault, extraOptions);
|
|
610
|
-
return depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions);
|
|
611
|
-
}
|
|
612
|
-
return depositSimple(signer, addresses, assets, receiver);
|
|
613
|
-
}
|
|
614
|
-
var LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
|
|
615
|
-
var EMPTY_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
616
|
-
var RECEIVED_HASH = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
617
|
-
async function ensureAllowance3(signer, token, spender, amount) {
|
|
618
|
-
const owner = await signer.getAddress();
|
|
619
|
-
const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
|
|
620
|
-
const current = await erc20.allowance(owner, spender);
|
|
621
|
-
if (current < amount) {
|
|
622
|
-
const tx = await erc20.approve(spender, amount);
|
|
623
|
-
await tx.wait();
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
async function depositFromSpoke(signer, spokeOFT, composer, hubEid, spokeEid, amount, receiver, lzFee, minMsgValue = 0n, minSharesOut = 0n, minAmountLD, extraOptions = "0x") {
|
|
627
|
-
await ensureAllowance3(signer, spokeOFT, spokeOFT, amount);
|
|
628
|
-
const oft = new ethers.Contract(spokeOFT, OFT_ABI, signer);
|
|
629
|
-
const refundAddress = await signer.getAddress();
|
|
630
|
-
const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
631
|
-
const composerBytes32 = ethers.zeroPadValue(composer, 32);
|
|
632
|
-
const hopSendParam = {
|
|
633
|
-
dstEid: spokeEid,
|
|
634
|
-
to: receiverBytes32,
|
|
635
|
-
amountLD: 0n,
|
|
636
|
-
minAmountLD: minSharesOut,
|
|
637
|
-
extraOptions: "0x",
|
|
638
|
-
composeMsg: "0x",
|
|
639
|
-
oftCmd: "0x"
|
|
640
|
-
};
|
|
641
|
-
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
642
|
-
const composeMsg = coder.encode(
|
|
643
|
-
[
|
|
644
|
-
"tuple(uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd)",
|
|
645
|
-
"uint256"
|
|
646
|
-
],
|
|
647
|
-
[hopSendParam, minMsgValue]
|
|
648
|
-
);
|
|
649
|
-
const sendParam = {
|
|
650
|
-
dstEid: hubEid,
|
|
651
|
-
to: composerBytes32,
|
|
652
|
-
amountLD: amount,
|
|
653
|
-
minAmountLD: minAmountLD ?? amount,
|
|
816
|
+
const sendParam = {
|
|
817
|
+
dstEid: hubEid,
|
|
818
|
+
to: composerBytes32,
|
|
819
|
+
amountLD: amount,
|
|
820
|
+
minAmountLD: minAmountLD ?? amount,
|
|
654
821
|
extraOptions,
|
|
655
822
|
composeMsg,
|
|
656
823
|
oftCmd: "0x"
|
|
@@ -691,68 +858,621 @@ async function quoteDepositFromSpokeFee(provider, spokeOFT, composer, hubEid, sp
|
|
|
691
858
|
minMsgValue
|
|
692
859
|
]
|
|
693
860
|
);
|
|
694
|
-
const sendParam = {
|
|
695
|
-
dstEid: hubEid,
|
|
696
|
-
to: composerBytes32,
|
|
697
|
-
amountLD: amount,
|
|
698
|
-
minAmountLD: minAmountLD ?? amount,
|
|
861
|
+
const sendParam = {
|
|
862
|
+
dstEid: hubEid,
|
|
863
|
+
to: composerBytes32,
|
|
864
|
+
amountLD: amount,
|
|
865
|
+
minAmountLD: minAmountLD ?? amount,
|
|
866
|
+
extraOptions,
|
|
867
|
+
composeMsg: composeMsgBytes,
|
|
868
|
+
oftCmd: "0x"
|
|
869
|
+
};
|
|
870
|
+
const oft = new ethers.Contract(spokeOFT, OFT_ABI, provider);
|
|
871
|
+
const fee = await oft.quoteSend(sendParam, false);
|
|
872
|
+
return fee.nativeFee;
|
|
873
|
+
}
|
|
874
|
+
async function quoteComposeFee(provider, vault, spokeEid, receiver) {
|
|
875
|
+
try {
|
|
876
|
+
const vaultContract = new ethers.Contract(vault, BRIDGE_ABI, provider);
|
|
877
|
+
const readFee = await vaultContract.quoteAccountingFee("0x");
|
|
878
|
+
let shareSendFee = 0n;
|
|
879
|
+
if (spokeEid && receiver) {
|
|
880
|
+
try {
|
|
881
|
+
const COMPOSER_ABI = ["function SHARE_OFT() view returns (address)"];
|
|
882
|
+
const FACTORY_ABI2 = ["function vaultComposer(address _vault) view returns (address)"];
|
|
883
|
+
const factory = new ethers.Contract("0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C", FACTORY_ABI2, provider);
|
|
884
|
+
const composerAddr = await factory.vaultComposer(vault);
|
|
885
|
+
const composer = new ethers.Contract(composerAddr, COMPOSER_ABI, provider);
|
|
886
|
+
const shareOftAddr = await composer.SHARE_OFT();
|
|
887
|
+
const shareOft = new ethers.Contract(shareOftAddr, OFT_ABI, provider);
|
|
888
|
+
const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
889
|
+
const fee = await shareOft.quoteSend({
|
|
890
|
+
dstEid: spokeEid,
|
|
891
|
+
to: receiverBytes32,
|
|
892
|
+
amountLD: 1000000n,
|
|
893
|
+
minAmountLD: 0n,
|
|
894
|
+
extraOptions: "0x",
|
|
895
|
+
composeMsg: "0x",
|
|
896
|
+
oftCmd: "0x"
|
|
897
|
+
}, false);
|
|
898
|
+
shareSendFee = fee.nativeFee;
|
|
899
|
+
} catch {
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return (readFee + shareSendFee) * 110n / 100n;
|
|
903
|
+
} catch {
|
|
904
|
+
return 500000000000000n;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async function executeCompose(signer, from, to, guid, message, fee, index = 0) {
|
|
908
|
+
const endpoint = new ethers.Contract(LZ_ENDPOINT, LZ_ENDPOINT_ABI, signer);
|
|
909
|
+
const hash = await endpoint.composeQueue(from, to, guid, index);
|
|
910
|
+
if (hash === EMPTY_HASH) {
|
|
911
|
+
throw new Error("Compose not found in queue (hash = 0). Never sent or wrong parameters.");
|
|
912
|
+
}
|
|
913
|
+
if (hash === RECEIVED_HASH) {
|
|
914
|
+
throw new Error("Compose already delivered \u2014 no action needed.");
|
|
915
|
+
}
|
|
916
|
+
const tx = await endpoint.lzCompose(from, to, guid, index, message, "0x", {
|
|
917
|
+
value: fee,
|
|
918
|
+
gasLimit: 5000000n
|
|
919
|
+
});
|
|
920
|
+
const receipt = await tx.wait();
|
|
921
|
+
return { receipt };
|
|
922
|
+
}
|
|
923
|
+
async function waitForCompose(hubProvider, composeData, receiver, pollIntervalMs = 2e4, timeoutMs = 18e5) {
|
|
924
|
+
const deadline = Date.now() + timeoutMs;
|
|
925
|
+
const composer = composeData.to.toLowerCase();
|
|
926
|
+
const endpoint = composeData.endpoint;
|
|
927
|
+
const receiverNeedle = receiver.replace(/^0x/, "").toLowerCase();
|
|
928
|
+
const startBlock = composeData.hubBlockStart;
|
|
929
|
+
const hubChainId = composeData.hubChainId;
|
|
930
|
+
const candidateAddresses = [];
|
|
931
|
+
for (const chainMap of Object.values(OFT_ROUTES)) {
|
|
932
|
+
const entry = chainMap[hubChainId];
|
|
933
|
+
if (entry) candidateAddresses.push(entry.oft.toLowerCase());
|
|
934
|
+
}
|
|
935
|
+
const stargateChecks = await Promise.all(
|
|
936
|
+
candidateAddresses.map(async (addr) => ({
|
|
937
|
+
addr,
|
|
938
|
+
isSg: await detectStargateOft(hubProvider, addr)
|
|
939
|
+
}))
|
|
940
|
+
);
|
|
941
|
+
const knownFromAddresses = stargateChecks.filter((c) => c.isSg).map((c) => c.addr);
|
|
942
|
+
const endpointContract = new ethers.Contract(endpoint, LZ_ENDPOINT_ABI, hubProvider);
|
|
943
|
+
const COMPOSE_SENT_TOPIC = "0x0c68e6a0b0fb0f33c52455a8da89b21fc640a3dd4a1b21d9bfcc8aeee4a43e84";
|
|
944
|
+
let attempt = 0;
|
|
945
|
+
let scannedUpTo = startBlock - 1n;
|
|
946
|
+
while (Date.now() < deadline) {
|
|
947
|
+
attempt++;
|
|
948
|
+
const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
|
|
949
|
+
try {
|
|
950
|
+
const currentBlock = BigInt(await hubProvider.getBlockNumber());
|
|
951
|
+
const chunkSize = 500n;
|
|
952
|
+
let from = scannedUpTo + 1n;
|
|
953
|
+
while (from <= currentBlock) {
|
|
954
|
+
const chunkEnd = from + chunkSize > currentBlock ? currentBlock : from + chunkSize;
|
|
955
|
+
try {
|
|
956
|
+
const logs = await hubProvider.getLogs({
|
|
957
|
+
address: endpoint,
|
|
958
|
+
topics: [COMPOSE_SENT_TOPIC],
|
|
959
|
+
fromBlock: `0x${from.toString(16)}`,
|
|
960
|
+
toBlock: `0x${chunkEnd.toString(16)}`
|
|
961
|
+
});
|
|
962
|
+
for (const log of logs) {
|
|
963
|
+
try {
|
|
964
|
+
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
965
|
+
const decoded = coder.decode(
|
|
966
|
+
["address", "address", "bytes32", "uint16", "bytes"],
|
|
967
|
+
log.data
|
|
968
|
+
);
|
|
969
|
+
const logFrom = decoded[0].toLowerCase();
|
|
970
|
+
const logTo = decoded[1].toLowerCase();
|
|
971
|
+
const logGuid = decoded[2];
|
|
972
|
+
const logIndex = Number(decoded[3]);
|
|
973
|
+
const logMessage = decoded[4];
|
|
974
|
+
if (logTo === composer && logMessage.toLowerCase().includes(receiverNeedle)) {
|
|
975
|
+
const hash = await endpointContract.composeQueue(
|
|
976
|
+
logFrom,
|
|
977
|
+
composer,
|
|
978
|
+
logGuid,
|
|
979
|
+
logIndex
|
|
980
|
+
);
|
|
981
|
+
if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
|
|
982
|
+
console.log(`[${elapsed}s] Poll #${attempt} \u2014 compose found! (block ${log.blockNumber})`);
|
|
983
|
+
return {
|
|
984
|
+
...composeData,
|
|
985
|
+
from: decoded[0],
|
|
986
|
+
to: composeData.to,
|
|
987
|
+
guid: logGuid,
|
|
988
|
+
index: logIndex,
|
|
989
|
+
message: logMessage
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
} catch {
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
} catch {
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
from = chunkEnd + 1n;
|
|
1000
|
+
}
|
|
1001
|
+
scannedUpTo = currentBlock;
|
|
1002
|
+
} catch {
|
|
1003
|
+
}
|
|
1004
|
+
let guidMatchFound = false;
|
|
1005
|
+
for (const fromAddr of knownFromAddresses) {
|
|
1006
|
+
try {
|
|
1007
|
+
const hash = await endpointContract.composeQueue(
|
|
1008
|
+
fromAddr,
|
|
1009
|
+
composer,
|
|
1010
|
+
composeData.guid,
|
|
1011
|
+
0
|
|
1012
|
+
);
|
|
1013
|
+
if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
|
|
1014
|
+
console.log(`[${elapsed}s] Poll #${attempt} \u2014 composeQueue confirms pending (GUID match), re-scanning for message...`);
|
|
1015
|
+
scannedUpTo = startBlock - 1n;
|
|
1016
|
+
guidMatchFound = true;
|
|
1017
|
+
}
|
|
1018
|
+
} catch {
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
if (!guidMatchFound) {
|
|
1022
|
+
console.log(`[${elapsed}s] Poll #${attempt} \u2014 compose not found yet, waiting ${pollIntervalMs / 1e3}s...`);
|
|
1023
|
+
}
|
|
1024
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
1025
|
+
}
|
|
1026
|
+
throw new Error(
|
|
1027
|
+
`Timeout waiting for compose after ${timeoutMs / 6e4} min. Check LayerZero scan for composer ${composeData.to}.`
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// src/ethers/preflight.ts
|
|
1032
|
+
async function preflightAsync(provider, vault, escrow) {
|
|
1033
|
+
const config = new ethers.Contract(vault, CONFIG_ABI, provider);
|
|
1034
|
+
const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
|
|
1035
|
+
const [ccManager, registeredEscrow, isHub, oraclesEnabled, isPaused] = await Promise.all([
|
|
1036
|
+
config.getCrossChainAccountingManager(),
|
|
1037
|
+
config.getEscrow(),
|
|
1038
|
+
config.isHub(),
|
|
1039
|
+
bridge.oraclesCrossChainAccounting(),
|
|
1040
|
+
config.paused()
|
|
1041
|
+
]);
|
|
1042
|
+
if (ccManager === ethers.ZeroAddress) {
|
|
1043
|
+
throw new Error(
|
|
1044
|
+
`[MoreVaults] CCManager not configured on vault ${vault}. Call setCrossChainAccountingManager(ccManagerAddress) as vault owner first.`
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
if (registeredEscrow === ethers.ZeroAddress) {
|
|
1048
|
+
throw new Error(
|
|
1049
|
+
`[MoreVaults] Escrow not configured for vault ${vault}. The registry must have an escrow set for this vault.`
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
if (!isHub) {
|
|
1053
|
+
throw new Error(
|
|
1054
|
+
`[MoreVaults] Vault ${vault} is not a hub vault. Async flows (D4/D5/R5) only work on hub vaults.`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
if (oraclesEnabled) {
|
|
1058
|
+
throw new Error(
|
|
1059
|
+
`[MoreVaults] Vault ${vault} has oracle-based cross-chain accounting enabled. Use depositSimple/depositCrossChainOracleOn instead of async flows.`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
if (isPaused) {
|
|
1063
|
+
throw new Error(
|
|
1064
|
+
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
async function preflightRedeemLiquidity(provider, vault, shares) {
|
|
1069
|
+
const config = new ethers.Contract(vault, CONFIG_ABI, provider);
|
|
1070
|
+
const bridge = new ethers.Contract(vault, BRIDGE_ABI, provider);
|
|
1071
|
+
const [isHub, oraclesEnabled] = await Promise.all([
|
|
1072
|
+
config.isHub(),
|
|
1073
|
+
bridge.oraclesCrossChainAccounting()
|
|
1074
|
+
]);
|
|
1075
|
+
if (!isHub || oraclesEnabled) return;
|
|
1076
|
+
const vaultContract = new ethers.Contract(vault, VAULT_ABI, provider);
|
|
1077
|
+
const underlying = await vaultContract.asset();
|
|
1078
|
+
const underlyingContract = new ethers.Contract(underlying, ERC20_ABI, provider);
|
|
1079
|
+
const [hubLiquid, assetsNeeded] = await Promise.all([
|
|
1080
|
+
underlyingContract.balanceOf(vault),
|
|
1081
|
+
vaultContract.convertToAssets(shares)
|
|
1082
|
+
]);
|
|
1083
|
+
if (hubLiquid < assetsNeeded) {
|
|
1084
|
+
throw new InsufficientLiquidityError(vault, hubLiquid, assetsNeeded);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
async function preflightSync(provider, vault) {
|
|
1088
|
+
const config = new ethers.Contract(vault, CONFIG_ABI, provider);
|
|
1089
|
+
const [isPaused, depositCapResult] = await Promise.all([
|
|
1090
|
+
config.paused(),
|
|
1091
|
+
config.maxDeposit(ethers.ZeroAddress).catch(() => null)
|
|
1092
|
+
]);
|
|
1093
|
+
if (isPaused) {
|
|
1094
|
+
throw new Error(
|
|
1095
|
+
`[MoreVaults] Vault ${vault} is paused. Cannot perform any actions.`
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
if (depositCapResult !== null && depositCapResult === 0n) {
|
|
1099
|
+
throw new Error(
|
|
1100
|
+
`[MoreVaults] Vault ${vault} has reached deposit capacity. No more deposits accepted.`
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
async function preflightSpokeDeposit(spokeProvider, vault, spokeOFT, hubEid, spokeEid, amount, userAddress, lzFee) {
|
|
1105
|
+
const OFT_TOKEN_ABI = ["function token() view returns (address)"];
|
|
1106
|
+
const oftContract = new ethers.Contract(spokeOFT, OFT_TOKEN_ABI, spokeProvider);
|
|
1107
|
+
const spokeToken = await oftContract.token();
|
|
1108
|
+
const tokenContract = new ethers.Contract(spokeToken, ERC20_ABI, spokeProvider);
|
|
1109
|
+
const [spokeTokenBalance, spokeNativeBalance] = await Promise.all([
|
|
1110
|
+
tokenContract.balanceOf(userAddress),
|
|
1111
|
+
spokeProvider.getBalance(userAddress)
|
|
1112
|
+
]);
|
|
1113
|
+
if (spokeTokenBalance < amount) {
|
|
1114
|
+
throw new Error(
|
|
1115
|
+
`[MoreVaults] Insufficient token balance on spoke chain.
|
|
1116
|
+
Need: ${amount}
|
|
1117
|
+
Have: ${spokeTokenBalance}
|
|
1118
|
+
Token: ${spokeToken}`
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
const gasBuffer = 500000000000000n;
|
|
1122
|
+
if (spokeNativeBalance < lzFee + gasBuffer) {
|
|
1123
|
+
throw new Error(
|
|
1124
|
+
`[MoreVaults] Insufficient native gas on spoke chain for TX1.
|
|
1125
|
+
Need: ~${lzFee + gasBuffer} wei (LZ fee + gas)
|
|
1126
|
+
Have: ${spokeNativeBalance} wei`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
const isStargate = await detectStargateOft(spokeProvider, spokeOFT);
|
|
1130
|
+
let hubNativeBalance = 0n;
|
|
1131
|
+
let estimatedComposeFee = 0n;
|
|
1132
|
+
if (isStargate) {
|
|
1133
|
+
const hubChainId = EID_TO_CHAIN_ID[hubEid];
|
|
1134
|
+
const hubProvider = createChainProvider(hubChainId);
|
|
1135
|
+
if (hubProvider) {
|
|
1136
|
+
[hubNativeBalance, estimatedComposeFee] = await Promise.all([
|
|
1137
|
+
hubProvider.getBalance(userAddress),
|
|
1138
|
+
quoteComposeFee(hubProvider, vault, spokeEid, userAddress)
|
|
1139
|
+
]);
|
|
1140
|
+
const hubGasBuffer = 300000000000000n;
|
|
1141
|
+
const totalNeeded = estimatedComposeFee + hubGasBuffer;
|
|
1142
|
+
if (hubNativeBalance < totalNeeded) {
|
|
1143
|
+
throw new Error(
|
|
1144
|
+
`[MoreVaults] Insufficient ETH on hub chain for TX2 (compose retry).
|
|
1145
|
+
This is a Stargate 2-TX flow \u2014 TX2 requires ETH on the hub chain.
|
|
1146
|
+
Need: ~${totalNeeded} wei (compose fee ${estimatedComposeFee} + gas)
|
|
1147
|
+
Have: ${hubNativeBalance} wei
|
|
1148
|
+
Short: ${totalNeeded - hubNativeBalance} wei
|
|
1149
|
+
Send ETH to ${userAddress} on chainId ${hubChainId} before depositing.`
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return {
|
|
1155
|
+
spokeTokenBalance,
|
|
1156
|
+
spokeNativeBalance,
|
|
1157
|
+
hubNativeBalance,
|
|
1158
|
+
estimatedComposeFee,
|
|
1159
|
+
isStargate
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
async function preflightSpokeRedeem(route, shares, userAddress, shareBridgeFee) {
|
|
1163
|
+
const spokeProvider = createChainProvider(route.spokeChainId);
|
|
1164
|
+
const hubProvider = createChainProvider(route.hubChainId);
|
|
1165
|
+
if (!spokeProvider) throw new Error(`No public RPC for spoke chainId ${route.spokeChainId}`);
|
|
1166
|
+
if (!hubProvider) throw new Error(`No public RPC for hub chainId ${route.hubChainId}`);
|
|
1167
|
+
const spokeShareContract = new ethers.Contract(route.spokeShareOft, ERC20_ABI, spokeProvider);
|
|
1168
|
+
const [sharesOnSpoke, spokeNativeBalance, hubNativeBalance] = await Promise.all([
|
|
1169
|
+
spokeShareContract.balanceOf(userAddress),
|
|
1170
|
+
spokeProvider.getBalance(userAddress),
|
|
1171
|
+
hubProvider.getBalance(userAddress)
|
|
1172
|
+
]);
|
|
1173
|
+
if (sharesOnSpoke < shares) {
|
|
1174
|
+
throw new Error(
|
|
1175
|
+
`[MoreVaults] Insufficient shares on spoke chain.
|
|
1176
|
+
Need: ${shares}
|
|
1177
|
+
Have: ${sharesOnSpoke}
|
|
1178
|
+
Token: ${route.spokeShareOft}`
|
|
1179
|
+
);
|
|
1180
|
+
}
|
|
1181
|
+
const spokeGasBuffer = 500000000000000n;
|
|
1182
|
+
if (spokeNativeBalance < shareBridgeFee + spokeGasBuffer) {
|
|
1183
|
+
throw new Error(
|
|
1184
|
+
`[MoreVaults] Insufficient native gas on spoke for TX1 (share bridge).
|
|
1185
|
+
Need: ~${shareBridgeFee + spokeGasBuffer} wei (LZ fee + gas)
|
|
1186
|
+
Have: ${spokeNativeBalance} wei`
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
let estimatedAssetBridgeFee = 0n;
|
|
1190
|
+
try {
|
|
1191
|
+
const toBytes32 = `0x${userAddress.replace(/^0x/, "").padStart(64, "0")}`;
|
|
1192
|
+
const dummyAmount = 1000000n;
|
|
1193
|
+
const hubOft = new ethers.Contract(route.hubAssetOft, OFT_ABI, hubProvider);
|
|
1194
|
+
const feeResult = await hubOft.quoteSend({
|
|
1195
|
+
dstEid: route.spokeEid,
|
|
1196
|
+
to: toBytes32,
|
|
1197
|
+
amountLD: dummyAmount,
|
|
1198
|
+
minAmountLD: dummyAmount * 99n / 100n,
|
|
1199
|
+
extraOptions: "0x",
|
|
1200
|
+
composeMsg: "0x",
|
|
1201
|
+
oftCmd: route.isStargate ? "0x01" : "0x"
|
|
1202
|
+
}, false);
|
|
1203
|
+
estimatedAssetBridgeFee = feeResult.nativeFee;
|
|
1204
|
+
} catch {
|
|
1205
|
+
estimatedAssetBridgeFee = 300000000000000n;
|
|
1206
|
+
}
|
|
1207
|
+
const hubGasBuffer = 300000000000000n;
|
|
1208
|
+
const totalHubNeeded = estimatedAssetBridgeFee + hubGasBuffer;
|
|
1209
|
+
if (hubNativeBalance < totalHubNeeded) {
|
|
1210
|
+
throw new Error(
|
|
1211
|
+
`[MoreVaults] Insufficient ETH on hub chain for TX2 (redeem) + TX3 (asset bridge).
|
|
1212
|
+
Need: ~${totalHubNeeded} wei (LZ fee ${estimatedAssetBridgeFee} + gas)
|
|
1213
|
+
Have: ${hubNativeBalance} wei
|
|
1214
|
+
Short: ${totalHubNeeded - hubNativeBalance} wei
|
|
1215
|
+
Send ETH to ${userAddress} on chainId ${route.hubChainId} before redeeming.`
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
return {
|
|
1219
|
+
sharesOnSpoke,
|
|
1220
|
+
spokeNativeBalance,
|
|
1221
|
+
hubNativeBalance,
|
|
1222
|
+
estimatedAssetBridgeFee,
|
|
1223
|
+
estimatedAssetsOut: 0n,
|
|
1224
|
+
hubLiquidBalance: 0n
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/ethers/chainValidation.ts
|
|
1229
|
+
async function validateWalletChain(signer, hubChainId) {
|
|
1230
|
+
if (!hubChainId) return;
|
|
1231
|
+
const network = await signer.provider?.getNetwork();
|
|
1232
|
+
if (!network) return;
|
|
1233
|
+
const current = Number(network.chainId);
|
|
1234
|
+
if (current !== hubChainId) {
|
|
1235
|
+
throw new WrongChainError(current, hubChainId);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// src/ethers/depositFlows.ts
|
|
1240
|
+
async function ensureAllowance3(signer, token, spender, amount) {
|
|
1241
|
+
const owner = await signer.getAddress();
|
|
1242
|
+
const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
|
|
1243
|
+
const current = await erc20.allowance(owner, spender);
|
|
1244
|
+
if (current < amount) {
|
|
1245
|
+
const tx = await erc20.approve(spender, amount);
|
|
1246
|
+
await tx.wait();
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
async function depositSimple(signer, addresses, assets, receiver) {
|
|
1250
|
+
const provider = signer.provider;
|
|
1251
|
+
await validateWalletChain(signer, addresses.hubChainId);
|
|
1252
|
+
await preflightSync(provider, addresses.vault);
|
|
1253
|
+
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
1254
|
+
const underlying = await vault.asset();
|
|
1255
|
+
await ensureAllowance3(signer, underlying, addresses.vault, assets);
|
|
1256
|
+
const tx = await vault["deposit(uint256,address)"](assets, receiver);
|
|
1257
|
+
const receipt = await tx.wait();
|
|
1258
|
+
let shares = 0n;
|
|
1259
|
+
for (const log of receipt.logs) {
|
|
1260
|
+
try {
|
|
1261
|
+
const parsed = vault.interface.parseLog({
|
|
1262
|
+
topics: log.topics,
|
|
1263
|
+
data: log.data
|
|
1264
|
+
});
|
|
1265
|
+
if (parsed && parsed.name === "Transfer" && parsed.args[0] === "0x0000000000000000000000000000000000000000") {
|
|
1266
|
+
shares = parsed.args[2];
|
|
1267
|
+
break;
|
|
1268
|
+
}
|
|
1269
|
+
} catch {
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return { receipt, shares };
|
|
1273
|
+
}
|
|
1274
|
+
async function depositMultiAsset(signer, addresses, tokens, amounts, receiver, minShares) {
|
|
1275
|
+
await validateWalletChain(signer, addresses.hubChainId);
|
|
1276
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1277
|
+
await ensureAllowance3(signer, tokens[i], addresses.vault, amounts[i]);
|
|
1278
|
+
}
|
|
1279
|
+
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
1280
|
+
const tx = await vault["deposit(address[],uint256[],address,uint256)"](tokens, amounts, receiver, minShares);
|
|
1281
|
+
const receipt = await tx.wait();
|
|
1282
|
+
let shares = 0n;
|
|
1283
|
+
for (const log of receipt.logs) {
|
|
1284
|
+
try {
|
|
1285
|
+
const parsed = vault.interface.parseLog({
|
|
1286
|
+
topics: log.topics,
|
|
1287
|
+
data: log.data
|
|
1288
|
+
});
|
|
1289
|
+
if (parsed && parsed.name === "Deposit") {
|
|
1290
|
+
shares = parsed.args[4];
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1293
|
+
} catch {
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return { receipt, shares };
|
|
1297
|
+
}
|
|
1298
|
+
var depositCrossChainOracleOn = depositSimple;
|
|
1299
|
+
async function depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions = "0x") {
|
|
1300
|
+
const provider = signer.provider;
|
|
1301
|
+
const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
|
|
1302
|
+
if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
|
|
1303
|
+
await validateWalletChain(signer, addresses.hubChainId);
|
|
1304
|
+
await preflightAsync(provider, addresses.vault);
|
|
1305
|
+
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
1306
|
+
const underlying = await vault.asset();
|
|
1307
|
+
await ensureAllowance3(signer, underlying, escrow, assets);
|
|
1308
|
+
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
1309
|
+
const actionCallData = coder.encode(
|
|
1310
|
+
["uint256", "address"],
|
|
1311
|
+
[assets, receiver]
|
|
1312
|
+
);
|
|
1313
|
+
const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
|
|
1314
|
+
const guid = await bridge.initVaultActionRequest.staticCall(
|
|
1315
|
+
ActionType.DEPOSIT,
|
|
1316
|
+
actionCallData,
|
|
1317
|
+
0,
|
|
1318
|
+
extraOptions,
|
|
1319
|
+
{ value: lzFee }
|
|
1320
|
+
);
|
|
1321
|
+
const tx = await bridge.initVaultActionRequest(
|
|
1322
|
+
ActionType.DEPOSIT,
|
|
1323
|
+
actionCallData,
|
|
1324
|
+
0,
|
|
1325
|
+
// amountLimit = 0 for deposits (minAmountOut handled by cross-chain manager)
|
|
1326
|
+
extraOptions,
|
|
1327
|
+
{ value: lzFee }
|
|
1328
|
+
);
|
|
1329
|
+
const receipt = await tx.wait();
|
|
1330
|
+
return { receipt, guid };
|
|
1331
|
+
}
|
|
1332
|
+
async function mintAsync(signer, addresses, shares, maxAssets, receiver, lzFee, extraOptions = "0x") {
|
|
1333
|
+
const provider = signer.provider;
|
|
1334
|
+
const escrow = addresses.escrow ?? await new ethers.Contract(addresses.vault, ["function getEscrow() view returns (address)"], provider).getEscrow();
|
|
1335
|
+
if (escrow === ethers.ZeroAddress) throw new EscrowNotConfiguredError(addresses.vault);
|
|
1336
|
+
await validateWalletChain(signer, addresses.hubChainId);
|
|
1337
|
+
await preflightAsync(provider, addresses.vault);
|
|
1338
|
+
const vault = new ethers.Contract(addresses.vault, VAULT_ABI, signer);
|
|
1339
|
+
const underlying = await vault.asset();
|
|
1340
|
+
await ensureAllowance3(signer, underlying, escrow, maxAssets);
|
|
1341
|
+
const coder = ethers.AbiCoder.defaultAbiCoder();
|
|
1342
|
+
const actionCallData = coder.encode(
|
|
1343
|
+
["uint256", "address"],
|
|
1344
|
+
[shares, receiver]
|
|
1345
|
+
);
|
|
1346
|
+
const bridge = new ethers.Contract(addresses.vault, BRIDGE_ABI, signer);
|
|
1347
|
+
const guid = await bridge.initVaultActionRequest.staticCall(
|
|
1348
|
+
ActionType.MINT,
|
|
1349
|
+
actionCallData,
|
|
1350
|
+
maxAssets,
|
|
1351
|
+
extraOptions,
|
|
1352
|
+
{ value: lzFee }
|
|
1353
|
+
);
|
|
1354
|
+
const tx = await bridge.initVaultActionRequest(
|
|
1355
|
+
ActionType.MINT,
|
|
1356
|
+
actionCallData,
|
|
1357
|
+
maxAssets,
|
|
699
1358
|
extraOptions,
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const fee = await oft.quoteSend(sendParam, false);
|
|
705
|
-
return fee.nativeFee;
|
|
1359
|
+
{ value: lzFee }
|
|
1360
|
+
);
|
|
1361
|
+
const receipt = await tx.wait();
|
|
1362
|
+
return { receipt, guid };
|
|
706
1363
|
}
|
|
707
|
-
async function
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
const shareOftAddr = await composer.SHARE_OFT();
|
|
720
|
-
const shareOft = new ethers.Contract(shareOftAddr, OFT_ABI, provider);
|
|
721
|
-
const receiverBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
722
|
-
const fee = await shareOft.quoteSend({
|
|
723
|
-
dstEid: spokeEid,
|
|
724
|
-
to: receiverBytes32,
|
|
725
|
-
amountLD: 1000000n,
|
|
726
|
-
minAmountLD: 0n,
|
|
727
|
-
extraOptions: "0x",
|
|
728
|
-
composeMsg: "0x",
|
|
729
|
-
oftCmd: "0x"
|
|
730
|
-
}, false);
|
|
731
|
-
shareSendFee = fee.nativeFee;
|
|
732
|
-
} catch {
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
return (readFee + shareSendFee) * 110n / 100n;
|
|
736
|
-
} catch {
|
|
737
|
-
return 500000000000000n;
|
|
1364
|
+
async function smartDeposit(signer, provider, addresses, assets, receiver, extraOptions = "0x") {
|
|
1365
|
+
const vault = addresses.vault;
|
|
1366
|
+
const status = await getVaultStatus(provider, vault);
|
|
1367
|
+
if (status.mode === "paused") {
|
|
1368
|
+
throw new VaultPausedError(vault);
|
|
1369
|
+
}
|
|
1370
|
+
if (status.mode === "full") {
|
|
1371
|
+
throw new CapacityFullError(vault);
|
|
1372
|
+
}
|
|
1373
|
+
if (status.recommendedDepositFlow === "depositAsync") {
|
|
1374
|
+
const lzFee = await quoteLzFee(provider, vault, extraOptions);
|
|
1375
|
+
return depositAsync(signer, addresses, assets, receiver, lzFee, extraOptions);
|
|
738
1376
|
}
|
|
1377
|
+
return depositSimple(signer, addresses, assets, receiver);
|
|
739
1378
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1379
|
+
var OMNI_FACTORY_ADDRESS = "0x7bDB8B17604b03125eFAED33cA0c55FBf856BB0C";
|
|
1380
|
+
var FACTORY_ABI = [
|
|
1381
|
+
"function localEid() view returns (uint32)",
|
|
1382
|
+
"function isCrossChainVault(uint32 __eid, address _vault) view returns (bool)",
|
|
1383
|
+
"function hubToSpokes(uint32 __eid, address _hubVault) view returns (uint32[] eids, address[] vaults)",
|
|
1384
|
+
"function spokeToHub(uint32 __eid, address _spokeVault) view returns (uint32 eid, address vault)"
|
|
1385
|
+
];
|
|
1386
|
+
var DISCOVERY_CHAIN_IDS = Object.values(CHAIN_IDS).filter(
|
|
1387
|
+
(id) => id !== 545
|
|
1388
|
+
// exclude testnet
|
|
1389
|
+
);
|
|
1390
|
+
async function getVaultTopology(provider, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
|
|
1391
|
+
const factory = new ethers.Contract(factoryAddress, FACTORY_ABI, provider);
|
|
1392
|
+
const localEid = Number(await factory.localEid());
|
|
1393
|
+
const isHub = await factory.isCrossChainVault(localEid, vault);
|
|
1394
|
+
if (isHub) {
|
|
1395
|
+
const result = await factory.hubToSpokes(localEid, vault);
|
|
1396
|
+
const spokeEids = result[0];
|
|
1397
|
+
const localChainId2 = EID_TO_CHAIN_ID[localEid] ?? 0;
|
|
1398
|
+
const spokeChainIds = spokeEids.map((eid) => EID_TO_CHAIN_ID[Number(eid)]).filter((id) => id !== void 0);
|
|
1399
|
+
return { role: "hub", hubChainId: localChainId2, spokeChainIds };
|
|
745
1400
|
}
|
|
746
|
-
|
|
747
|
-
|
|
1401
|
+
const spokeResult = await factory.spokeToHub(localEid, vault);
|
|
1402
|
+
const hubEid = Number(spokeResult[0]);
|
|
1403
|
+
const hubVault = spokeResult[1];
|
|
1404
|
+
if (hubEid !== 0 && hubVault !== "0x0000000000000000000000000000000000000000") {
|
|
1405
|
+
const hubChainId = EID_TO_CHAIN_ID[hubEid] ?? 0;
|
|
1406
|
+
const spokeChainIds = [];
|
|
1407
|
+
const localChainId2 = EID_TO_CHAIN_ID[localEid];
|
|
1408
|
+
if (localChainId2 !== void 0) spokeChainIds.push(localChainId2);
|
|
1409
|
+
return { role: "spoke", hubChainId, spokeChainIds };
|
|
748
1410
|
}
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const
|
|
754
|
-
|
|
1411
|
+
const localChainId = EID_TO_CHAIN_ID[localEid] ?? 0;
|
|
1412
|
+
return { role: "local", hubChainId: localChainId, spokeChainIds: [] };
|
|
1413
|
+
}
|
|
1414
|
+
async function getFullVaultTopology(hubChainProvider, vault, factoryAddress = OMNI_FACTORY_ADDRESS) {
|
|
1415
|
+
const topo = await getVaultTopology(hubChainProvider, vault, factoryAddress);
|
|
1416
|
+
if (topo.role !== "hub") {
|
|
1417
|
+
throw new Error(
|
|
1418
|
+
`getFullVaultTopology: provider must be connected to the hub chain (${topo.hubChainId}), but got role="${topo.role}". Connect to chainId ${topo.hubChainId} instead.`
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
return topo;
|
|
1422
|
+
}
|
|
1423
|
+
async function discoverVaultTopology(vault, provider, factoryAddress = OMNI_FACTORY_ADDRESS) {
|
|
1424
|
+
let triedChainId;
|
|
1425
|
+
if (provider) {
|
|
1426
|
+
try {
|
|
1427
|
+
const topo = await getVaultTopology(provider, vault, factoryAddress);
|
|
1428
|
+
if (topo.role !== "local") {
|
|
1429
|
+
if (topo.role === "spoke") {
|
|
1430
|
+
const hubProvider = createChainProvider(topo.hubChainId);
|
|
1431
|
+
if (hubProvider) {
|
|
1432
|
+
try {
|
|
1433
|
+
return await getFullVaultTopology(hubProvider, vault, factoryAddress);
|
|
1434
|
+
} catch {
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
return topo;
|
|
1439
|
+
}
|
|
1440
|
+
const network = await provider.getNetwork();
|
|
1441
|
+
triedChainId = Number(network.chainId);
|
|
1442
|
+
} catch {
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
for (const chainId of DISCOVERY_CHAIN_IDS) {
|
|
1446
|
+
if (chainId === triedChainId) continue;
|
|
1447
|
+
const chainProvider = createChainProvider(chainId);
|
|
1448
|
+
if (!chainProvider) continue;
|
|
1449
|
+
try {
|
|
1450
|
+
const topo = await getVaultTopology(chainProvider, vault, factoryAddress);
|
|
1451
|
+
if (topo.role === "hub") return topo;
|
|
1452
|
+
if (topo.role === "spoke") {
|
|
1453
|
+
const hubProvider = createChainProvider(topo.hubChainId);
|
|
1454
|
+
if (hubProvider) {
|
|
1455
|
+
try {
|
|
1456
|
+
return await getFullVaultTopology(hubProvider, vault, factoryAddress);
|
|
1457
|
+
} catch {
|
|
1458
|
+
return topo;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
return topo;
|
|
1462
|
+
}
|
|
1463
|
+
} catch {
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return { role: "local", hubChainId: 0, spokeChainIds: [] };
|
|
755
1467
|
}
|
|
1468
|
+
function isOnHubChain(currentChainId, topology) {
|
|
1469
|
+
return currentChainId === topology.hubChainId;
|
|
1470
|
+
}
|
|
1471
|
+
function getAllVaultChainIds(topology) {
|
|
1472
|
+
return [topology.hubChainId, ...topology.spokeChainIds];
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/ethers/redeemFlows.ts
|
|
756
1476
|
async function ensureAllowance4(signer, token, spender, amount) {
|
|
757
1477
|
const owner = await signer.getAddress();
|
|
758
1478
|
const erc20 = new ethers.Contract(token, ERC20_ABI, signer);
|
|
@@ -886,6 +1606,83 @@ async function bridgeAssetsToSpoke(signer, assetOFT, spokeChainEid, amount, rece
|
|
|
886
1606
|
const receipt = await tx.wait();
|
|
887
1607
|
return { receipt };
|
|
888
1608
|
}
|
|
1609
|
+
var FACTORY_COMPOSER_ABI_RF = [
|
|
1610
|
+
"function vaultComposer(address _vault) view returns (address)"
|
|
1611
|
+
];
|
|
1612
|
+
var REDEEM_COMPOSER_ABI = [
|
|
1613
|
+
"function SHARE_OFT() view returns (address)"
|
|
1614
|
+
];
|
|
1615
|
+
var OFT_PEERS_ABI_RF = [
|
|
1616
|
+
"function peers(uint32 eid) view returns (bytes32)"
|
|
1617
|
+
];
|
|
1618
|
+
async function quoteShareBridgeFee(spokeProvider, shareOFT, hubChainEid, amountLD, receiver) {
|
|
1619
|
+
const toBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
1620
|
+
const sendParam = {
|
|
1621
|
+
dstEid: hubChainEid,
|
|
1622
|
+
to: toBytes32,
|
|
1623
|
+
amountLD,
|
|
1624
|
+
minAmountLD: amountLD,
|
|
1625
|
+
extraOptions: "0x",
|
|
1626
|
+
composeMsg: "0x",
|
|
1627
|
+
oftCmd: "0x"
|
|
1628
|
+
};
|
|
1629
|
+
const oft = new ethers.Contract(shareOFT, OFT_ABI, spokeProvider);
|
|
1630
|
+
const fee = await oft.quoteSend(sendParam, false);
|
|
1631
|
+
return fee.nativeFee;
|
|
1632
|
+
}
|
|
1633
|
+
async function resolveRedeemAddresses(hubProvider, vault, hubChainId, spokeChainId) {
|
|
1634
|
+
const hubEid = CHAIN_ID_TO_EID[hubChainId];
|
|
1635
|
+
const spokeEid = CHAIN_ID_TO_EID[spokeChainId];
|
|
1636
|
+
if (!hubEid || !spokeEid) {
|
|
1637
|
+
throw new Error(`No LZ EID for chainId ${!hubEid ? hubChainId : spokeChainId}`);
|
|
1638
|
+
}
|
|
1639
|
+
const vaultContract = new ethers.Contract(vault, VAULT_ABI, hubProvider);
|
|
1640
|
+
const factory = new ethers.Contract(OMNI_FACTORY_ADDRESS, FACTORY_COMPOSER_ABI_RF, hubProvider);
|
|
1641
|
+
const [hubAsset, composerAddress] = await Promise.all([
|
|
1642
|
+
vaultContract.asset(),
|
|
1643
|
+
factory.vaultComposer(vault)
|
|
1644
|
+
]);
|
|
1645
|
+
if (composerAddress === ethers.ZeroAddress) {
|
|
1646
|
+
throw new Error(`[MoreVaults] No composer registered for vault ${vault} on hub chain ${hubChainId}`);
|
|
1647
|
+
}
|
|
1648
|
+
const composer = new ethers.Contract(composerAddress, REDEEM_COMPOSER_ABI, hubProvider);
|
|
1649
|
+
const hubShareOft = await composer.SHARE_OFT();
|
|
1650
|
+
const hubShareOftContract = new ethers.Contract(hubShareOft, OFT_PEERS_ABI_RF, hubProvider);
|
|
1651
|
+
const spokeShareOftBytes32 = await hubShareOftContract.peers(spokeEid);
|
|
1652
|
+
const spokeShareOft = `0x${spokeShareOftBytes32.slice(-40)}`;
|
|
1653
|
+
let hubAssetOft = null;
|
|
1654
|
+
let spokeAsset = null;
|
|
1655
|
+
let symbol = "";
|
|
1656
|
+
for (const [sym, chainMap] of Object.entries(OFT_ROUTES)) {
|
|
1657
|
+
const hubEntry = chainMap[hubChainId];
|
|
1658
|
+
const spokeEntry = chainMap[spokeChainId];
|
|
1659
|
+
if (!hubEntry || !spokeEntry) continue;
|
|
1660
|
+
if (hubEntry.token.toLowerCase() === hubAsset.toLowerCase()) {
|
|
1661
|
+
hubAssetOft = hubEntry.oft;
|
|
1662
|
+
spokeAsset = spokeEntry.token;
|
|
1663
|
+
symbol = sym;
|
|
1664
|
+
break;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
if (!hubAssetOft || !spokeAsset) {
|
|
1668
|
+
throw new Error(
|
|
1669
|
+
`[MoreVaults] No OFT route found for vault asset ${hubAsset} between hub chain ${hubChainId} and spoke chain ${spokeChainId}`
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
const isStargate = await detectStargateOft(hubProvider, hubAssetOft);
|
|
1673
|
+
return {
|
|
1674
|
+
hubChainId,
|
|
1675
|
+
spokeChainId,
|
|
1676
|
+
hubEid,
|
|
1677
|
+
spokeEid,
|
|
1678
|
+
hubAsset,
|
|
1679
|
+
spokeShareOft,
|
|
1680
|
+
hubAssetOft,
|
|
1681
|
+
spokeAsset,
|
|
1682
|
+
isStargate,
|
|
1683
|
+
symbol
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
889
1686
|
var MULTICALL3_ADDRESS2 = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
890
1687
|
var MULTICALL3_ABI2 = [
|
|
891
1688
|
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
|
|
@@ -955,11 +1752,11 @@ async function canDeposit(provider, vault, user) {
|
|
|
955
1752
|
return { allowed: true, reason: "ok" };
|
|
956
1753
|
}
|
|
957
1754
|
async function getVaultMetadata(provider, vault) {
|
|
958
|
-
const
|
|
959
|
-
const
|
|
1755
|
+
const MULTICALL3_ADDRESS4 = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
1756
|
+
const MULTICALL3_ABI4 = [
|
|
960
1757
|
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
|
|
961
1758
|
];
|
|
962
|
-
const mc = new ethers.Contract(
|
|
1759
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS4, MULTICALL3_ABI4, provider);
|
|
963
1760
|
const metaIface = new ethers.Interface(METADATA_ABI);
|
|
964
1761
|
const vaultIface = new ethers.Interface(VAULT_ABI);
|
|
965
1762
|
const b1Calls = [
|
|
@@ -1096,6 +1893,644 @@ async function getVaultSummary(provider, vault) {
|
|
|
1096
1893
|
]);
|
|
1097
1894
|
return { ...status, ...metadata };
|
|
1098
1895
|
}
|
|
1896
|
+
var FACTORY_COMPOSER_ABI_UH = [
|
|
1897
|
+
"function vaultComposer(address _vault) view returns (address)"
|
|
1898
|
+
];
|
|
1899
|
+
var COMPOSER_SHARE_OFT_ABI_UH = [
|
|
1900
|
+
"function SHARE_OFT() view returns (address)"
|
|
1901
|
+
];
|
|
1902
|
+
var OFT_PEERS_ABI_UH = [
|
|
1903
|
+
"function peers(uint32 eid) view returns (bytes32)"
|
|
1904
|
+
];
|
|
1905
|
+
async function getUserPositionMultiChain(vault, user) {
|
|
1906
|
+
const topo = await discoverVaultTopology(vault);
|
|
1907
|
+
const hubProvider = createChainProvider(topo.hubChainId);
|
|
1908
|
+
if (!hubProvider) throw new Error(`No public RPC for hub chainId ${topo.hubChainId}`);
|
|
1909
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS2, MULTICALL3_ABI2, hubProvider);
|
|
1910
|
+
const vaultIface = new ethers.Interface(VAULT_ABI);
|
|
1911
|
+
const decimalsIface = new ethers.Interface(["function decimals() view returns (uint8)"]);
|
|
1912
|
+
const b1Calls = [
|
|
1913
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("balanceOf", [user]) },
|
|
1914
|
+
{ target: vault, allowFailure: false, callData: decimalsIface.encodeFunctionData("decimals") },
|
|
1915
|
+
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("getWithdrawalRequest", [user]) }
|
|
1916
|
+
];
|
|
1917
|
+
const [b1Raw, block] = await Promise.all([
|
|
1918
|
+
mc.aggregate3.staticCall(b1Calls),
|
|
1919
|
+
hubProvider.getBlock("latest")
|
|
1920
|
+
]);
|
|
1921
|
+
const hubShares = vaultIface.decodeFunctionResult("balanceOf", b1Raw[0].returnData)[0];
|
|
1922
|
+
const decimals = Number(decimalsIface.decodeFunctionResult("decimals", b1Raw[1].returnData)[0]);
|
|
1923
|
+
const withdrawalResult = vaultIface.decodeFunctionResult("getWithdrawalRequest", b1Raw[2].returnData);
|
|
1924
|
+
const withdrawShares = withdrawalResult[0];
|
|
1925
|
+
const timelockEndsAt = withdrawalResult[1];
|
|
1926
|
+
const spokeShares = {};
|
|
1927
|
+
const rawSpokeShares = {};
|
|
1928
|
+
if (topo.spokeChainIds.length > 0) {
|
|
1929
|
+
let hubShareOft = null;
|
|
1930
|
+
try {
|
|
1931
|
+
const factory = new ethers.Contract(OMNI_FACTORY_ADDRESS, FACTORY_COMPOSER_ABI_UH, hubProvider);
|
|
1932
|
+
const composerAddress = await factory.vaultComposer(vault);
|
|
1933
|
+
if (composerAddress !== "0x0000000000000000000000000000000000000000") {
|
|
1934
|
+
const composer = new ethers.Contract(composerAddress, COMPOSER_SHARE_OFT_ABI_UH, hubProvider);
|
|
1935
|
+
hubShareOft = await composer.SHARE_OFT();
|
|
1936
|
+
}
|
|
1937
|
+
} catch {
|
|
1938
|
+
}
|
|
1939
|
+
if (hubShareOft) {
|
|
1940
|
+
const hubShareOftContract = new ethers.Contract(hubShareOft, OFT_PEERS_ABI_UH, hubProvider);
|
|
1941
|
+
const spokePromises = topo.spokeChainIds.map(async (spokeChainId) => {
|
|
1942
|
+
try {
|
|
1943
|
+
const spokeEid = CHAIN_ID_TO_EID[spokeChainId];
|
|
1944
|
+
if (!spokeEid) return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
|
|
1945
|
+
const spokeOftBytes32 = await hubShareOftContract.peers(spokeEid);
|
|
1946
|
+
const spokeOft = `0x${spokeOftBytes32.slice(-40)}`;
|
|
1947
|
+
if (spokeOft === "0x0000000000000000000000000000000000000000") {
|
|
1948
|
+
return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
|
|
1949
|
+
}
|
|
1950
|
+
const spokeProvider = createChainProvider(spokeChainId);
|
|
1951
|
+
if (!spokeProvider) return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
|
|
1952
|
+
const spokeMc = new ethers.Contract(MULTICALL3_ADDRESS2, MULTICALL3_ABI2, spokeProvider);
|
|
1953
|
+
const erc20Iface = new ethers.Interface(ERC20_ABI);
|
|
1954
|
+
const spokeDecimalsIface = new ethers.Interface(["function decimals() view returns (uint8)"]);
|
|
1955
|
+
const spokeCalls = [
|
|
1956
|
+
{ target: spokeOft, allowFailure: false, callData: erc20Iface.encodeFunctionData("balanceOf", [user]) },
|
|
1957
|
+
{ target: spokeOft, allowFailure: false, callData: spokeDecimalsIface.encodeFunctionData("decimals") }
|
|
1958
|
+
];
|
|
1959
|
+
const spokeRaw = await spokeMc.aggregate3.staticCall(spokeCalls);
|
|
1960
|
+
const rawBalance = erc20Iface.decodeFunctionResult("balanceOf", spokeRaw[0].returnData)[0];
|
|
1961
|
+
const spokeOftDecimals = Number(spokeDecimalsIface.decodeFunctionResult("decimals", spokeRaw[1].returnData)[0]);
|
|
1962
|
+
let balance;
|
|
1963
|
+
if (spokeOftDecimals > decimals) {
|
|
1964
|
+
balance = rawBalance / 10n ** BigInt(spokeOftDecimals - decimals);
|
|
1965
|
+
} else if (spokeOftDecimals < decimals) {
|
|
1966
|
+
balance = rawBalance * 10n ** BigInt(decimals - spokeOftDecimals);
|
|
1967
|
+
} else {
|
|
1968
|
+
balance = rawBalance;
|
|
1969
|
+
}
|
|
1970
|
+
return { chainId: spokeChainId, balance, rawBalance };
|
|
1971
|
+
} catch {
|
|
1972
|
+
return { chainId: spokeChainId, balance: 0n, rawBalance: 0n };
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
const results = await Promise.all(spokePromises);
|
|
1976
|
+
for (const { chainId, balance, rawBalance } of results) {
|
|
1977
|
+
spokeShares[chainId] = balance;
|
|
1978
|
+
rawSpokeShares[chainId] = rawBalance;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
const totalSpokeShares = Object.values(spokeShares).reduce((sum, b) => sum + b, 0n);
|
|
1983
|
+
const totalShares = hubShares + totalSpokeShares;
|
|
1984
|
+
const oneShare = 10n ** BigInt(decimals);
|
|
1985
|
+
const vaultContract = new ethers.Contract(vault, VAULT_ABI, hubProvider);
|
|
1986
|
+
const [estimatedAssets, sharePrice] = await Promise.all([
|
|
1987
|
+
totalShares === 0n ? Promise.resolve(0n) : vaultContract.convertToAssets(totalShares),
|
|
1988
|
+
vaultContract.convertToAssets(oneShare)
|
|
1989
|
+
]);
|
|
1990
|
+
const currentTimestamp = BigInt(block?.timestamp ?? 0);
|
|
1991
|
+
const pendingWithdrawal = withdrawShares === 0n ? null : {
|
|
1992
|
+
shares: withdrawShares,
|
|
1993
|
+
timelockEndsAt,
|
|
1994
|
+
canRedeemNow: timelockEndsAt === 0n || currentTimestamp >= timelockEndsAt
|
|
1995
|
+
};
|
|
1996
|
+
return {
|
|
1997
|
+
hubShares,
|
|
1998
|
+
spokeShares,
|
|
1999
|
+
rawSpokeShares,
|
|
2000
|
+
totalShares,
|
|
2001
|
+
estimatedAssets,
|
|
2002
|
+
sharePrice,
|
|
2003
|
+
decimals,
|
|
2004
|
+
pendingWithdrawal
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
var MULTICALL3_ADDRESS3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
2008
|
+
var MULTICALL3_ABI3 = [
|
|
2009
|
+
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
|
|
2010
|
+
];
|
|
2011
|
+
async function getCuratorVaultStatus(provider, vault) {
|
|
2012
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
|
|
2013
|
+
const curatorConfigIface = new ethers.Interface(CURATOR_CONFIG_ABI);
|
|
2014
|
+
const multicallIface = new ethers.Interface(MULTICALL_ABI);
|
|
2015
|
+
const calls = [
|
|
2016
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("curator") },
|
|
2017
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("timeLockPeriod") },
|
|
2018
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getMaxSlippagePercent") },
|
|
2019
|
+
{ target: vault, allowFailure: false, callData: multicallIface.encodeFunctionData("getCurrentNonce") },
|
|
2020
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getAvailableAssets") },
|
|
2021
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("getCrossChainAccountingManager") },
|
|
2022
|
+
{ target: vault, allowFailure: false, callData: curatorConfigIface.encodeFunctionData("paused") }
|
|
2023
|
+
];
|
|
2024
|
+
const results = await mc.aggregate3.staticCall(calls);
|
|
2025
|
+
const curator = curatorConfigIface.decodeFunctionResult("curator", results[0].returnData)[0];
|
|
2026
|
+
const timeLockPeriod = curatorConfigIface.decodeFunctionResult("timeLockPeriod", results[1].returnData)[0];
|
|
2027
|
+
const maxSlippagePercent = curatorConfigIface.decodeFunctionResult("getMaxSlippagePercent", results[2].returnData)[0];
|
|
2028
|
+
const currentNonce = multicallIface.decodeFunctionResult("getCurrentNonce", results[3].returnData)[0];
|
|
2029
|
+
const availableAssets = curatorConfigIface.decodeFunctionResult("getAvailableAssets", results[4].returnData)[0];
|
|
2030
|
+
const lzAdapter = curatorConfigIface.decodeFunctionResult("getCrossChainAccountingManager", results[5].returnData)[0];
|
|
2031
|
+
const paused = curatorConfigIface.decodeFunctionResult("paused", results[6].returnData)[0];
|
|
2032
|
+
return {
|
|
2033
|
+
curator,
|
|
2034
|
+
timeLockPeriod,
|
|
2035
|
+
maxSlippagePercent,
|
|
2036
|
+
currentNonce,
|
|
2037
|
+
availableAssets,
|
|
2038
|
+
lzAdapter,
|
|
2039
|
+
paused
|
|
2040
|
+
};
|
|
2041
|
+
}
|
|
2042
|
+
async function getPendingActions(provider, vault, nonce) {
|
|
2043
|
+
const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, provider);
|
|
2044
|
+
const [result, block] = await Promise.all([
|
|
2045
|
+
multicallContract.getPendingActions(nonce),
|
|
2046
|
+
provider.getBlock("latest")
|
|
2047
|
+
]);
|
|
2048
|
+
const [actionsData, pendingUntil] = result;
|
|
2049
|
+
const currentTimestamp = BigInt(block.timestamp);
|
|
2050
|
+
const isExecutable = pendingUntil > 0n && currentTimestamp >= pendingUntil;
|
|
2051
|
+
return {
|
|
2052
|
+
nonce,
|
|
2053
|
+
actionsData,
|
|
2054
|
+
pendingUntil,
|
|
2055
|
+
isExecutable
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
async function isCurator(provider, vault, address) {
|
|
2059
|
+
const config = new ethers.Contract(vault, CURATOR_CONFIG_ABI, provider);
|
|
2060
|
+
const curatorAddress = await config.curator();
|
|
2061
|
+
return curatorAddress.toLowerCase() === address.toLowerCase();
|
|
2062
|
+
}
|
|
2063
|
+
async function getVaultAnalysis(provider, vault) {
|
|
2064
|
+
const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
|
|
2065
|
+
const [availableRaw, depositableRaw, depositWhitelistEnabled, registryResult] = await Promise.all([
|
|
2066
|
+
analysisContract.getAvailableAssets(),
|
|
2067
|
+
analysisContract.getDepositableAssets(),
|
|
2068
|
+
analysisContract.isDepositWhitelistEnabled(),
|
|
2069
|
+
analysisContract.moreVaultsRegistry().catch(() => null)
|
|
2070
|
+
]);
|
|
2071
|
+
const availableAddresses = availableRaw;
|
|
2072
|
+
const depositableAddresses = depositableRaw;
|
|
2073
|
+
const allAddresses = Array.from(/* @__PURE__ */ new Set([...availableAddresses, ...depositableAddresses]));
|
|
2074
|
+
const assetInfoMap = /* @__PURE__ */ new Map();
|
|
2075
|
+
if (allAddresses.length > 0) {
|
|
2076
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
|
|
2077
|
+
const metaIface = new ethers.Interface(METADATA_ABI);
|
|
2078
|
+
const metadataCalls = allAddresses.flatMap((addr) => [
|
|
2079
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("name") },
|
|
2080
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("symbol") },
|
|
2081
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
|
|
2082
|
+
]);
|
|
2083
|
+
const metadataResults = await mc.aggregate3.staticCall(metadataCalls);
|
|
2084
|
+
for (let i = 0; i < allAddresses.length; i++) {
|
|
2085
|
+
const addr = allAddresses[i];
|
|
2086
|
+
const nameRes = metadataResults[i * 3];
|
|
2087
|
+
const symbolRes = metadataResults[i * 3 + 1];
|
|
2088
|
+
const decimalsRes = metadataResults[i * 3 + 2];
|
|
2089
|
+
const name = nameRes.success ? metaIface.decodeFunctionResult("name", nameRes.returnData)[0] : "";
|
|
2090
|
+
const symbol = symbolRes.success ? metaIface.decodeFunctionResult("symbol", symbolRes.returnData)[0] : "";
|
|
2091
|
+
const decimals = decimalsRes.success ? Number(metaIface.decodeFunctionResult("decimals", decimalsRes.returnData)[0]) : 18;
|
|
2092
|
+
assetInfoMap.set(addr.toLowerCase(), { address: addr, name, symbol, decimals });
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
const registryAddress = registryResult ? registryResult : null;
|
|
2096
|
+
return {
|
|
2097
|
+
availableAssets: availableAddresses.map((a) => assetInfoMap.get(a.toLowerCase())),
|
|
2098
|
+
depositableAssets: depositableAddresses.map((a) => assetInfoMap.get(a.toLowerCase())),
|
|
2099
|
+
depositWhitelistEnabled,
|
|
2100
|
+
registryAddress
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
async function checkProtocolWhitelist(provider, vault, protocols) {
|
|
2104
|
+
const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
|
|
2105
|
+
const registry = await analysisContract.moreVaultsRegistry();
|
|
2106
|
+
if (protocols.length === 0) return {};
|
|
2107
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
|
|
2108
|
+
const registryIface = new ethers.Interface(REGISTRY_ABI);
|
|
2109
|
+
const calls = protocols.map((protocol) => ({
|
|
2110
|
+
target: registry,
|
|
2111
|
+
allowFailure: true,
|
|
2112
|
+
callData: registryIface.encodeFunctionData("isWhitelisted", [protocol])
|
|
2113
|
+
}));
|
|
2114
|
+
const results = await mc.aggregate3.staticCall(calls);
|
|
2115
|
+
const out = {};
|
|
2116
|
+
for (let i = 0; i < protocols.length; i++) {
|
|
2117
|
+
const r = results[i];
|
|
2118
|
+
const whitelisted = r.success ? registryIface.decodeFunctionResult("isWhitelisted", r.returnData)[0] : false;
|
|
2119
|
+
out[protocols[i].toLowerCase()] = whitelisted;
|
|
2120
|
+
}
|
|
2121
|
+
return out;
|
|
2122
|
+
}
|
|
2123
|
+
async function getVaultAssetBreakdown(provider, vault) {
|
|
2124
|
+
const analysisContract = new ethers.Contract(vault, VAULT_ANALYSIS_ABI, provider);
|
|
2125
|
+
const availableRaw = await analysisContract.getAvailableAssets();
|
|
2126
|
+
const addresses = availableRaw;
|
|
2127
|
+
const mc = new ethers.Contract(MULTICALL3_ADDRESS3, MULTICALL3_ABI3, provider);
|
|
2128
|
+
const vaultIface = new ethers.Interface(VAULT_ABI);
|
|
2129
|
+
const metaIface = new ethers.Interface(METADATA_ABI);
|
|
2130
|
+
const erc20Iface = new ethers.Interface(ERC20_ABI);
|
|
2131
|
+
const perAssetCalls = addresses.flatMap((addr) => [
|
|
2132
|
+
{ target: addr, allowFailure: true, callData: erc20Iface.encodeFunctionData("balanceOf", [vault]) },
|
|
2133
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("name") },
|
|
2134
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("symbol") },
|
|
2135
|
+
{ target: addr, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
|
|
2136
|
+
]);
|
|
2137
|
+
const totalCalls = [
|
|
2138
|
+
...perAssetCalls,
|
|
2139
|
+
{ target: vault, allowFailure: true, callData: vaultIface.encodeFunctionData("totalAssets") },
|
|
2140
|
+
{ target: vault, allowFailure: true, callData: vaultIface.encodeFunctionData("totalSupply") },
|
|
2141
|
+
{ target: vault, allowFailure: true, callData: metaIface.encodeFunctionData("decimals") }
|
|
2142
|
+
];
|
|
2143
|
+
const results = await mc.aggregate3.staticCall(totalCalls);
|
|
2144
|
+
const perAssetFields = 4;
|
|
2145
|
+
const assets = addresses.map((addr, i) => {
|
|
2146
|
+
const base = i * perAssetFields;
|
|
2147
|
+
const balance = results[base].success ? erc20Iface.decodeFunctionResult("balanceOf", results[base].returnData)[0] : 0n;
|
|
2148
|
+
const name = results[base + 1].success ? metaIface.decodeFunctionResult("name", results[base + 1].returnData)[0] : "";
|
|
2149
|
+
const symbol = results[base + 2].success ? metaIface.decodeFunctionResult("symbol", results[base + 2].returnData)[0] : "";
|
|
2150
|
+
const decimals = results[base + 3].success ? Number(metaIface.decodeFunctionResult("decimals", results[base + 3].returnData)[0]) : 18;
|
|
2151
|
+
return { address: addr, name, symbol, decimals, balance };
|
|
2152
|
+
});
|
|
2153
|
+
const totalsBase = addresses.length * perAssetFields;
|
|
2154
|
+
const totalAssets = results[totalsBase].success ? vaultIface.decodeFunctionResult("totalAssets", results[totalsBase].returnData)[0] : 0n;
|
|
2155
|
+
const totalSupply = results[totalsBase + 1].success ? vaultIface.decodeFunctionResult("totalSupply", results[totalsBase + 1].returnData)[0] : 0n;
|
|
2156
|
+
const underlyingDecimals = results[totalsBase + 2].success ? Number(metaIface.decodeFunctionResult("decimals", results[totalsBase + 2].returnData)[0]) : 6;
|
|
2157
|
+
return { assets, totalAssets, totalSupply, underlyingDecimals };
|
|
2158
|
+
}
|
|
2159
|
+
function encodeCuratorAction(action) {
|
|
2160
|
+
switch (action.type) {
|
|
2161
|
+
case "swap": {
|
|
2162
|
+
const iface = new ethers.Interface(DEX_ABI);
|
|
2163
|
+
return iface.encodeFunctionData("executeSwap", [
|
|
2164
|
+
{
|
|
2165
|
+
targetContract: action.params.targetContract,
|
|
2166
|
+
tokenIn: action.params.tokenIn,
|
|
2167
|
+
tokenOut: action.params.tokenOut,
|
|
2168
|
+
maxAmountIn: action.params.maxAmountIn,
|
|
2169
|
+
minAmountOut: action.params.minAmountOut,
|
|
2170
|
+
swapCallData: action.params.swapCallData
|
|
2171
|
+
}
|
|
2172
|
+
]);
|
|
2173
|
+
}
|
|
2174
|
+
case "batchSwap": {
|
|
2175
|
+
const iface = new ethers.Interface(DEX_ABI);
|
|
2176
|
+
return iface.encodeFunctionData("executeBatchSwap", [
|
|
2177
|
+
{
|
|
2178
|
+
swaps: action.params.swaps.map((s) => ({
|
|
2179
|
+
targetContract: s.targetContract,
|
|
2180
|
+
tokenIn: s.tokenIn,
|
|
2181
|
+
tokenOut: s.tokenOut,
|
|
2182
|
+
maxAmountIn: s.maxAmountIn,
|
|
2183
|
+
minAmountOut: s.minAmountOut,
|
|
2184
|
+
swapCallData: s.swapCallData
|
|
2185
|
+
}))
|
|
2186
|
+
}
|
|
2187
|
+
]);
|
|
2188
|
+
}
|
|
2189
|
+
case "erc4626Deposit": {
|
|
2190
|
+
const iface = new ethers.Interface(ERC4626_FACET_ABI);
|
|
2191
|
+
return iface.encodeFunctionData("erc4626Deposit", [action.vault, action.assets]);
|
|
2192
|
+
}
|
|
2193
|
+
case "erc4626Redeem": {
|
|
2194
|
+
const iface = new ethers.Interface(ERC4626_FACET_ABI);
|
|
2195
|
+
return iface.encodeFunctionData("erc4626Redeem", [action.vault, action.shares]);
|
|
2196
|
+
}
|
|
2197
|
+
case "erc7540RequestDeposit": {
|
|
2198
|
+
const iface = new ethers.Interface(ERC7540_FACET_ABI);
|
|
2199
|
+
return iface.encodeFunctionData("erc7540RequestDeposit", [action.vault, action.assets]);
|
|
2200
|
+
}
|
|
2201
|
+
case "erc7540Deposit": {
|
|
2202
|
+
const iface = new ethers.Interface(ERC7540_FACET_ABI);
|
|
2203
|
+
return iface.encodeFunctionData("erc7540Deposit", [action.vault, action.assets]);
|
|
2204
|
+
}
|
|
2205
|
+
case "erc7540RequestRedeem": {
|
|
2206
|
+
const iface = new ethers.Interface(ERC7540_FACET_ABI);
|
|
2207
|
+
return iface.encodeFunctionData("erc7540RequestRedeem", [action.vault, action.shares]);
|
|
2208
|
+
}
|
|
2209
|
+
case "erc7540Redeem": {
|
|
2210
|
+
const iface = new ethers.Interface(ERC7540_FACET_ABI);
|
|
2211
|
+
return iface.encodeFunctionData("erc7540Redeem", [action.vault, action.shares]);
|
|
2212
|
+
}
|
|
2213
|
+
default: {
|
|
2214
|
+
const _exhaustive = action;
|
|
2215
|
+
throw new Error(`[MoreVaults] Unknown CuratorAction type: ${_exhaustive.type}`);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
function buildCuratorBatch(actions) {
|
|
2220
|
+
return actions.map(encodeCuratorAction);
|
|
2221
|
+
}
|
|
2222
|
+
async function submitActions(signer, vault, actions) {
|
|
2223
|
+
const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
|
|
2224
|
+
const tx = await multicallContract.submitActions(actions);
|
|
2225
|
+
const receipt = await tx.wait();
|
|
2226
|
+
const nextNonce = await multicallContract.getCurrentNonce();
|
|
2227
|
+
const nonce = nextNonce - 1n;
|
|
2228
|
+
return { receipt, nonce };
|
|
2229
|
+
}
|
|
2230
|
+
async function executeActions(signer, vault, nonce) {
|
|
2231
|
+
const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
|
|
2232
|
+
const tx = await multicallContract.executeActions(nonce);
|
|
2233
|
+
return tx.wait();
|
|
2234
|
+
}
|
|
2235
|
+
async function vetoActions(signer, vault, nonces) {
|
|
2236
|
+
const multicallContract = new ethers.Contract(vault, MULTICALL_ABI, signer);
|
|
2237
|
+
const tx = await multicallContract.vetoActions(nonces);
|
|
2238
|
+
return tx.wait();
|
|
2239
|
+
}
|
|
2240
|
+
var UNISWAP_V3_SWAP_ROUTER_ABI = [
|
|
2241
|
+
"function exactInputSingle(tuple(address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)"
|
|
2242
|
+
];
|
|
2243
|
+
var UNISWAP_V3_SWAP_ROUTER02_ABI = [
|
|
2244
|
+
"function exactInputSingle(tuple(address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)"
|
|
2245
|
+
];
|
|
2246
|
+
var SWAP_ROUTER02_CHAINS = /* @__PURE__ */ new Set([8453]);
|
|
2247
|
+
function encodeUniswapV3SwapCalldata(params) {
|
|
2248
|
+
const { chainId, tokenIn, tokenOut, fee, amountIn, minAmountOut, recipient } = params;
|
|
2249
|
+
const router = UNISWAP_V3_ROUTERS[chainId];
|
|
2250
|
+
if (!router) {
|
|
2251
|
+
throw new Error(
|
|
2252
|
+
`[MoreVaults] No Uniswap V3 router configured for chainId ${chainId}. Supported chains: ${Object.keys(UNISWAP_V3_ROUTERS).join(", ")}`
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
let swapCallData;
|
|
2256
|
+
if (SWAP_ROUTER02_CHAINS.has(chainId)) {
|
|
2257
|
+
const iface = new ethers.Interface(UNISWAP_V3_SWAP_ROUTER02_ABI);
|
|
2258
|
+
swapCallData = iface.encodeFunctionData("exactInputSingle", [
|
|
2259
|
+
{
|
|
2260
|
+
tokenIn,
|
|
2261
|
+
tokenOut,
|
|
2262
|
+
fee,
|
|
2263
|
+
recipient,
|
|
2264
|
+
amountIn,
|
|
2265
|
+
amountOutMinimum: minAmountOut,
|
|
2266
|
+
sqrtPriceLimitX96: 0n
|
|
2267
|
+
}
|
|
2268
|
+
]);
|
|
2269
|
+
} else {
|
|
2270
|
+
const deadline = BigInt(Math.floor(Date.now() / 1e3) + 1200);
|
|
2271
|
+
const iface = new ethers.Interface(UNISWAP_V3_SWAP_ROUTER_ABI);
|
|
2272
|
+
swapCallData = iface.encodeFunctionData("exactInputSingle", [
|
|
2273
|
+
{
|
|
2274
|
+
tokenIn,
|
|
2275
|
+
tokenOut,
|
|
2276
|
+
fee,
|
|
2277
|
+
recipient,
|
|
2278
|
+
deadline,
|
|
2279
|
+
amountIn,
|
|
2280
|
+
amountOutMinimum: minAmountOut,
|
|
2281
|
+
sqrtPriceLimitX96: 0n
|
|
2282
|
+
}
|
|
2283
|
+
]);
|
|
2284
|
+
}
|
|
2285
|
+
return { targetContract: router, swapCallData };
|
|
2286
|
+
}
|
|
2287
|
+
function buildUniswapV3Swap(params) {
|
|
2288
|
+
const { targetContract, swapCallData } = encodeUniswapV3SwapCalldata(params);
|
|
2289
|
+
return {
|
|
2290
|
+
type: "swap",
|
|
2291
|
+
params: {
|
|
2292
|
+
targetContract,
|
|
2293
|
+
tokenIn: params.tokenIn,
|
|
2294
|
+
tokenOut: params.tokenOut,
|
|
2295
|
+
maxAmountIn: params.amountIn,
|
|
2296
|
+
minAmountOut: params.minAmountOut,
|
|
2297
|
+
swapCallData
|
|
2298
|
+
}
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
// src/ethers/distribution.ts
|
|
2303
|
+
async function getVaultDistribution(hubProvider, vault, spokeProviders) {
|
|
2304
|
+
const hubStatus = await getVaultStatus(hubProvider, vault);
|
|
2305
|
+
const hubChainId = Number((await hubProvider.getNetwork()).chainId);
|
|
2306
|
+
const hubTotalAssets = hubStatus.totalAssets;
|
|
2307
|
+
const hubLiquidBalance = hubStatus.hubLiquidBalance;
|
|
2308
|
+
const hubStrategyBalance = hubTotalAssets > hubLiquidBalance ? hubTotalAssets - hubLiquidBalance : 0n;
|
|
2309
|
+
const spokeEntries = Object.entries(spokeProviders).map(([chainIdStr, provider]) => ({
|
|
2310
|
+
chainId: Number(chainIdStr),
|
|
2311
|
+
provider
|
|
2312
|
+
}));
|
|
2313
|
+
const spokeBalances = await Promise.all(
|
|
2314
|
+
spokeEntries.map(async ({ chainId, provider }) => {
|
|
2315
|
+
try {
|
|
2316
|
+
const spokeStatus = await getVaultStatus(provider, vault);
|
|
2317
|
+
return { chainId, totalAssets: spokeStatus.totalAssets, isReachable: true };
|
|
2318
|
+
} catch {
|
|
2319
|
+
return { chainId, totalAssets: 0n, isReachable: false };
|
|
2320
|
+
}
|
|
2321
|
+
})
|
|
2322
|
+
);
|
|
2323
|
+
const reachableSpokeSum = spokeBalances.filter((s) => s.isReachable).reduce((acc, s) => acc + s.totalAssets, 0n);
|
|
2324
|
+
const totalActual = hubTotalAssets + reachableSpokeSum;
|
|
2325
|
+
return {
|
|
2326
|
+
hubChainId,
|
|
2327
|
+
hubLiquidBalance,
|
|
2328
|
+
hubStrategyBalance,
|
|
2329
|
+
hubTotalAssets,
|
|
2330
|
+
spokesDeployedBalance: hubStatus.spokesDeployedBalance,
|
|
2331
|
+
spokeBalances,
|
|
2332
|
+
totalActual,
|
|
2333
|
+
oracleAccountingEnabled: hubStatus.oracleAccountingEnabled
|
|
2334
|
+
};
|
|
2335
|
+
}
|
|
2336
|
+
async function getVaultDistributionWithTopology(hubProvider, vault) {
|
|
2337
|
+
const [hubStatus, topology] = await Promise.all([
|
|
2338
|
+
getVaultStatus(hubProvider, vault),
|
|
2339
|
+
getVaultTopology(hubProvider, vault)
|
|
2340
|
+
]);
|
|
2341
|
+
const hubChainId = Number((await hubProvider.getNetwork()).chainId);
|
|
2342
|
+
const hubTotalAssets = hubStatus.totalAssets;
|
|
2343
|
+
const hubLiquidBalance = hubStatus.hubLiquidBalance;
|
|
2344
|
+
const hubStrategyBalance = hubTotalAssets > hubLiquidBalance ? hubTotalAssets - hubLiquidBalance : 0n;
|
|
2345
|
+
return {
|
|
2346
|
+
hubChainId,
|
|
2347
|
+
hubLiquidBalance,
|
|
2348
|
+
hubStrategyBalance,
|
|
2349
|
+
hubTotalAssets,
|
|
2350
|
+
spokesDeployedBalance: hubStatus.spokesDeployedBalance,
|
|
2351
|
+
spokeBalances: [],
|
|
2352
|
+
totalActual: hubTotalAssets,
|
|
2353
|
+
// hub-only, no spoke data
|
|
2354
|
+
oracleAccountingEnabled: hubStatus.oracleAccountingEnabled,
|
|
2355
|
+
spokeChainIds: topology.spokeChainIds
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
var NATIVE_SYMBOL = {
|
|
2359
|
+
1: "ETH",
|
|
2360
|
+
10: "ETH",
|
|
2361
|
+
42161: "ETH",
|
|
2362
|
+
8453: "ETH",
|
|
2363
|
+
747: "FLOW",
|
|
2364
|
+
146: "S",
|
|
2365
|
+
56: "BNB"
|
|
2366
|
+
};
|
|
2367
|
+
var SYMBOL_ABI = [
|
|
2368
|
+
"function symbol() view returns (string)"
|
|
2369
|
+
];
|
|
2370
|
+
async function readTokenSymbol(provider, token, fallbackSymbol) {
|
|
2371
|
+
if (!provider) return fallbackSymbol;
|
|
2372
|
+
try {
|
|
2373
|
+
const contract = new ethers.Contract(token, SYMBOL_ABI, provider);
|
|
2374
|
+
return await contract.symbol();
|
|
2375
|
+
} catch {
|
|
2376
|
+
return fallbackSymbol;
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
async function getInboundRoutes(hubChainId, vault, vaultAsset, userAddress) {
|
|
2380
|
+
const hubEid = CHAIN_ID_TO_EID[hubChainId];
|
|
2381
|
+
if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
|
|
2382
|
+
const hubProvider = createChainProvider(hubChainId);
|
|
2383
|
+
if (!hubProvider) throw new Error(`No public RPC for hub chainId ${hubChainId}`);
|
|
2384
|
+
const topology = await getVaultTopology(hubProvider, vault);
|
|
2385
|
+
const registeredSpokes = new Set(topology.spokeChainIds);
|
|
2386
|
+
const results = [];
|
|
2387
|
+
const vaultAssetNorm = vaultAsset.toLowerCase();
|
|
2388
|
+
for (const [symbol, chainMap] of Object.entries(OFT_ROUTES)) {
|
|
2389
|
+
const hubEntry = chainMap[hubChainId];
|
|
2390
|
+
if (!hubEntry) continue;
|
|
2391
|
+
if (hubEntry.token.toLowerCase() !== vaultAssetNorm) continue;
|
|
2392
|
+
const oftCmd = "0x";
|
|
2393
|
+
const spokesToCheck = Object.keys(chainMap).map(Number).filter((id) => id !== hubChainId && registeredSpokes.has(id));
|
|
2394
|
+
await Promise.allSettled(
|
|
2395
|
+
spokesToCheck.map(async (spokeChainId) => {
|
|
2396
|
+
const spokeEntry = chainMap[spokeChainId];
|
|
2397
|
+
if (!spokeEntry) return;
|
|
2398
|
+
const spokeProvider = createChainProvider(spokeChainId);
|
|
2399
|
+
if (!spokeProvider) return;
|
|
2400
|
+
try {
|
|
2401
|
+
const receiverBytes32 = "0x" + userAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0");
|
|
2402
|
+
const spokeOft = new ethers.Contract(spokeEntry.oft, OFT_ABI, spokeProvider);
|
|
2403
|
+
const [feeResult, sourceTokenSymbol] = await Promise.all([
|
|
2404
|
+
spokeOft.quoteSend(
|
|
2405
|
+
{
|
|
2406
|
+
dstEid: hubEid,
|
|
2407
|
+
to: receiverBytes32,
|
|
2408
|
+
amountLD: 1000000n,
|
|
2409
|
+
minAmountLD: 0n,
|
|
2410
|
+
extraOptions: "0x",
|
|
2411
|
+
composeMsg: "0x",
|
|
2412
|
+
oftCmd
|
|
2413
|
+
},
|
|
2414
|
+
false
|
|
2415
|
+
),
|
|
2416
|
+
readTokenSymbol(spokeProvider, spokeEntry.token, symbol)
|
|
2417
|
+
]);
|
|
2418
|
+
results.push({
|
|
2419
|
+
symbol,
|
|
2420
|
+
spokeChainId,
|
|
2421
|
+
depositType: "oft-compose",
|
|
2422
|
+
spokeOft: spokeEntry.oft,
|
|
2423
|
+
spokeToken: spokeEntry.token,
|
|
2424
|
+
sourceTokenSymbol,
|
|
2425
|
+
hubOft: hubEntry.oft,
|
|
2426
|
+
oftCmd,
|
|
2427
|
+
lzFeeEstimate: feeResult.nativeFee,
|
|
2428
|
+
nativeSymbol: NATIVE_SYMBOL[spokeChainId] ?? "ETH"
|
|
2429
|
+
});
|
|
2430
|
+
} catch {
|
|
2431
|
+
}
|
|
2432
|
+
})
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
const [asyncMode, ...hubOftEntries] = await Promise.all([
|
|
2436
|
+
isAsyncMode(hubProvider, vault),
|
|
2437
|
+
...Object.entries(OFT_ROUTES).map(async ([sym, chainMap]) => {
|
|
2438
|
+
const hubEntry = chainMap[hubChainId];
|
|
2439
|
+
if (!hubEntry || hubEntry.token.toLowerCase() !== vaultAssetNorm) return null;
|
|
2440
|
+
return { symbol: sym, hubEntry };
|
|
2441
|
+
})
|
|
2442
|
+
]);
|
|
2443
|
+
const hubOftEntry = hubOftEntries.find((e) => e !== null) ?? null;
|
|
2444
|
+
if (hubOftEntry) {
|
|
2445
|
+
const { symbol, hubEntry } = hubOftEntry;
|
|
2446
|
+
const [sourceTokenSymbol, lzFeeEstimate] = await Promise.all([
|
|
2447
|
+
readTokenSymbol(hubProvider, hubEntry.token, symbol),
|
|
2448
|
+
asyncMode ? quoteLzFee(hubProvider, vault) : Promise.resolve(0n)
|
|
2449
|
+
]);
|
|
2450
|
+
results.unshift({
|
|
2451
|
+
symbol,
|
|
2452
|
+
spokeChainId: hubChainId,
|
|
2453
|
+
depositType: asyncMode ? "direct-async" : "direct",
|
|
2454
|
+
spokeOft: null,
|
|
2455
|
+
spokeToken: hubEntry.token,
|
|
2456
|
+
sourceTokenSymbol,
|
|
2457
|
+
hubOft: null,
|
|
2458
|
+
oftCmd: "0x",
|
|
2459
|
+
lzFeeEstimate,
|
|
2460
|
+
nativeSymbol: NATIVE_SYMBOL[hubChainId] ?? "ETH"
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
return results;
|
|
2464
|
+
}
|
|
2465
|
+
async function getUserBalancesForRoutes(routes, userAddress) {
|
|
2466
|
+
return Promise.all(
|
|
2467
|
+
routes.map(async (route) => {
|
|
2468
|
+
const provider = createChainProvider(route.spokeChainId);
|
|
2469
|
+
if (!provider) return { ...route, userBalance: 0n };
|
|
2470
|
+
try {
|
|
2471
|
+
let userBalance;
|
|
2472
|
+
if (route.spokeToken.toLowerCase() === ethers.ZeroAddress.toLowerCase()) {
|
|
2473
|
+
userBalance = await provider.getBalance(userAddress);
|
|
2474
|
+
} else {
|
|
2475
|
+
const erc20 = new ethers.Contract(route.spokeToken, ERC20_ABI, provider);
|
|
2476
|
+
userBalance = await erc20.balanceOf(userAddress);
|
|
2477
|
+
}
|
|
2478
|
+
return { ...route, userBalance };
|
|
2479
|
+
} catch {
|
|
2480
|
+
return { ...route, userBalance: 0n };
|
|
2481
|
+
}
|
|
2482
|
+
})
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
async function getOutboundRoutes(hubChainId, vault) {
|
|
2486
|
+
const hubEid = CHAIN_ID_TO_EID[hubChainId];
|
|
2487
|
+
if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
|
|
2488
|
+
const hubProvider = createChainProvider(hubChainId);
|
|
2489
|
+
if (!hubProvider) throw new Error(`No public RPC for hub chainId ${hubChainId}`);
|
|
2490
|
+
const topology = await getVaultTopology(hubProvider, vault);
|
|
2491
|
+
const routes = [
|
|
2492
|
+
{
|
|
2493
|
+
chainId: hubChainId,
|
|
2494
|
+
routeType: "hub",
|
|
2495
|
+
eid: hubEid,
|
|
2496
|
+
nativeSymbol: NATIVE_SYMBOL[hubChainId] ?? "ETH"
|
|
2497
|
+
}
|
|
2498
|
+
];
|
|
2499
|
+
for (const spokeChainId of topology.spokeChainIds) {
|
|
2500
|
+
const eid = CHAIN_ID_TO_EID[spokeChainId];
|
|
2501
|
+
if (!eid) continue;
|
|
2502
|
+
routes.push({
|
|
2503
|
+
chainId: spokeChainId,
|
|
2504
|
+
routeType: "spoke",
|
|
2505
|
+
eid,
|
|
2506
|
+
nativeSymbol: NATIVE_SYMBOL[spokeChainId] ?? "ETH"
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2509
|
+
return routes;
|
|
2510
|
+
}
|
|
2511
|
+
async function quoteRouteDepositFee(route, hubChainId, amount, userAddress) {
|
|
2512
|
+
if (route.depositType === "direct") return 0n;
|
|
2513
|
+
const hubEid = CHAIN_ID_TO_EID[hubChainId];
|
|
2514
|
+
if (!hubEid) throw new Error(`No LZ EID for hub chainId ${hubChainId}`);
|
|
2515
|
+
if (!route.spokeOft) throw new Error("Route is oft-compose but spokeOft is null");
|
|
2516
|
+
const spokeProvider = createChainProvider(route.spokeChainId);
|
|
2517
|
+
if (!spokeProvider) throw new Error(`No public RPC for spoke chainId ${route.spokeChainId}`);
|
|
2518
|
+
const receiverBytes32 = "0x" + userAddress.replace(/^0x/, "").toLowerCase().padStart(64, "0");
|
|
2519
|
+
const spokeOft = new ethers.Contract(route.spokeOft, OFT_ABI, spokeProvider);
|
|
2520
|
+
const feeResult = await spokeOft.quoteSend(
|
|
2521
|
+
{
|
|
2522
|
+
dstEid: hubEid,
|
|
2523
|
+
to: receiverBytes32,
|
|
2524
|
+
amountLD: amount,
|
|
2525
|
+
minAmountLD: 0n,
|
|
2526
|
+
extraOptions: "0x",
|
|
2527
|
+
composeMsg: "0x",
|
|
2528
|
+
oftCmd: route.oftCmd
|
|
2529
|
+
},
|
|
2530
|
+
false
|
|
2531
|
+
);
|
|
2532
|
+
return feeResult.nativeFee;
|
|
2533
|
+
}
|
|
1099
2534
|
|
|
1100
2535
|
// src/ethers/wagmiCompat.ts
|
|
1101
2536
|
function asSdkSigner(signer) {
|
|
@@ -1105,63 +2540,107 @@ function asSdkSigner(signer) {
|
|
|
1105
2540
|
|
|
1106
2541
|
exports.ActionType = ActionType;
|
|
1107
2542
|
exports.BRIDGE_ABI = BRIDGE_ABI;
|
|
2543
|
+
exports.BRIDGE_FACET_ABI = BRIDGE_FACET_ABI;
|
|
1108
2544
|
exports.CCManagerNotConfiguredError = CCManagerNotConfiguredError;
|
|
1109
2545
|
exports.CHAIN_IDS = CHAIN_IDS;
|
|
1110
2546
|
exports.CHAIN_ID_TO_EID = CHAIN_ID_TO_EID;
|
|
1111
2547
|
exports.CONFIG_ABI = CONFIG_ABI;
|
|
2548
|
+
exports.CURATOR_CONFIG_ABI = CURATOR_CONFIG_ABI;
|
|
1112
2549
|
exports.CapacityFullError = CapacityFullError;
|
|
2550
|
+
exports.DEX_ABI = DEX_ABI;
|
|
1113
2551
|
exports.EID_TO_CHAIN_ID = EID_TO_CHAIN_ID;
|
|
1114
2552
|
exports.ERC20_ABI = ERC20_ABI;
|
|
2553
|
+
exports.ERC4626_FACET_ABI = ERC4626_FACET_ABI;
|
|
2554
|
+
exports.ERC7540_FACET_ABI = ERC7540_FACET_ABI;
|
|
1115
2555
|
exports.EscrowNotConfiguredError = EscrowNotConfiguredError;
|
|
1116
2556
|
exports.InsufficientLiquidityError = InsufficientLiquidityError;
|
|
2557
|
+
exports.LZ_ADAPTER_ABI = LZ_ADAPTER_ABI;
|
|
1117
2558
|
exports.LZ_EIDS = LZ_EIDS;
|
|
1118
2559
|
exports.LZ_ENDPOINT_ABI = LZ_ENDPOINT_ABI;
|
|
1119
2560
|
exports.LZ_TIMEOUTS = LZ_TIMEOUTS;
|
|
1120
2561
|
exports.METADATA_ABI = METADATA_ABI;
|
|
2562
|
+
exports.MULTICALL_ABI = MULTICALL_ABI;
|
|
1121
2563
|
exports.MissingEscrowAddressError = MissingEscrowAddressError;
|
|
1122
2564
|
exports.MoreVaultsError = MoreVaultsError;
|
|
2565
|
+
exports.NATIVE_SYMBOL = NATIVE_SYMBOL;
|
|
1123
2566
|
exports.NotHubVaultError = NotHubVaultError;
|
|
1124
2567
|
exports.NotWhitelistedError = NotWhitelistedError;
|
|
1125
2568
|
exports.OFT_ABI = OFT_ABI;
|
|
2569
|
+
exports.OFT_ROUTES = OFT_ROUTES;
|
|
2570
|
+
exports.OMNI_FACTORY_ADDRESS = OMNI_FACTORY_ADDRESS;
|
|
2571
|
+
exports.REGISTRY_ABI = REGISTRY_ABI;
|
|
2572
|
+
exports.UNISWAP_V3_ROUTERS = UNISWAP_V3_ROUTERS;
|
|
1126
2573
|
exports.VAULT_ABI = VAULT_ABI;
|
|
2574
|
+
exports.VAULT_ANALYSIS_ABI = VAULT_ANALYSIS_ABI;
|
|
1127
2575
|
exports.VaultPausedError = VaultPausedError;
|
|
1128
2576
|
exports.WrongChainError = WrongChainError;
|
|
1129
2577
|
exports.asSdkSigner = asSdkSigner;
|
|
1130
2578
|
exports.bridgeAssetsToSpoke = bridgeAssetsToSpoke;
|
|
1131
2579
|
exports.bridgeSharesToHub = bridgeSharesToHub;
|
|
2580
|
+
exports.buildCuratorBatch = buildCuratorBatch;
|
|
2581
|
+
exports.buildUniswapV3Swap = buildUniswapV3Swap;
|
|
1132
2582
|
exports.canDeposit = canDeposit;
|
|
2583
|
+
exports.checkProtocolWhitelist = checkProtocolWhitelist;
|
|
1133
2584
|
exports.depositAsync = depositAsync;
|
|
1134
2585
|
exports.depositCrossChainOracleOn = depositCrossChainOracleOn;
|
|
1135
2586
|
exports.depositFromSpoke = depositFromSpoke;
|
|
1136
2587
|
exports.depositFromSpokeAsync = depositFromSpokeAsync;
|
|
1137
2588
|
exports.depositMultiAsset = depositMultiAsset;
|
|
1138
2589
|
exports.depositSimple = depositSimple;
|
|
2590
|
+
exports.detectStargateOft = detectStargateOft;
|
|
2591
|
+
exports.discoverVaultTopology = discoverVaultTopology;
|
|
2592
|
+
exports.encodeCuratorAction = encodeCuratorAction;
|
|
2593
|
+
exports.encodeUniswapV3SwapCalldata = encodeUniswapV3SwapCalldata;
|
|
1139
2594
|
exports.ensureAllowance = ensureAllowance;
|
|
2595
|
+
exports.executeActions = executeActions;
|
|
1140
2596
|
exports.executeCompose = executeCompose;
|
|
2597
|
+
exports.getAllVaultChainIds = getAllVaultChainIds;
|
|
1141
2598
|
exports.getAsyncRequestStatus = getAsyncRequestStatus;
|
|
1142
2599
|
exports.getAsyncRequestStatusLabel = getAsyncRequestStatusLabel;
|
|
2600
|
+
exports.getCuratorVaultStatus = getCuratorVaultStatus;
|
|
2601
|
+
exports.getFullVaultTopology = getFullVaultTopology;
|
|
2602
|
+
exports.getInboundRoutes = getInboundRoutes;
|
|
1143
2603
|
exports.getMaxWithdrawable = getMaxWithdrawable;
|
|
2604
|
+
exports.getOutboundRoutes = getOutboundRoutes;
|
|
2605
|
+
exports.getPendingActions = getPendingActions;
|
|
1144
2606
|
exports.getUserBalances = getUserBalances;
|
|
2607
|
+
exports.getUserBalancesForRoutes = getUserBalancesForRoutes;
|
|
1145
2608
|
exports.getUserPosition = getUserPosition;
|
|
2609
|
+
exports.getUserPositionMultiChain = getUserPositionMultiChain;
|
|
2610
|
+
exports.getVaultAnalysis = getVaultAnalysis;
|
|
2611
|
+
exports.getVaultAssetBreakdown = getVaultAssetBreakdown;
|
|
2612
|
+
exports.getVaultDistribution = getVaultDistribution;
|
|
2613
|
+
exports.getVaultDistributionWithTopology = getVaultDistributionWithTopology;
|
|
1146
2614
|
exports.getVaultMetadata = getVaultMetadata;
|
|
1147
2615
|
exports.getVaultStatus = getVaultStatus;
|
|
1148
2616
|
exports.getVaultSummary = getVaultSummary;
|
|
2617
|
+
exports.getVaultTopology = getVaultTopology;
|
|
1149
2618
|
exports.getWithdrawalRequest = getWithdrawalRequest;
|
|
1150
2619
|
exports.isAsyncMode = isAsyncMode;
|
|
2620
|
+
exports.isCurator = isCurator;
|
|
2621
|
+
exports.isOnHubChain = isOnHubChain;
|
|
1151
2622
|
exports.mintAsync = mintAsync;
|
|
1152
2623
|
exports.preflightAsync = preflightAsync;
|
|
1153
2624
|
exports.preflightRedeemLiquidity = preflightRedeemLiquidity;
|
|
2625
|
+
exports.preflightSpokeDeposit = preflightSpokeDeposit;
|
|
2626
|
+
exports.preflightSpokeRedeem = preflightSpokeRedeem;
|
|
1154
2627
|
exports.preflightSync = preflightSync;
|
|
1155
2628
|
exports.previewDeposit = previewDeposit;
|
|
1156
2629
|
exports.previewRedeem = previewRedeem;
|
|
1157
2630
|
exports.quoteComposeFee = quoteComposeFee;
|
|
1158
2631
|
exports.quoteDepositFromSpokeFee = quoteDepositFromSpokeFee;
|
|
1159
2632
|
exports.quoteLzFee = quoteLzFee;
|
|
2633
|
+
exports.quoteRouteDepositFee = quoteRouteDepositFee;
|
|
2634
|
+
exports.quoteShareBridgeFee = quoteShareBridgeFee;
|
|
1160
2635
|
exports.redeemAsync = redeemAsync;
|
|
1161
2636
|
exports.redeemShares = redeemShares;
|
|
1162
2637
|
exports.requestRedeem = requestRedeem;
|
|
2638
|
+
exports.resolveRedeemAddresses = resolveRedeemAddresses;
|
|
1163
2639
|
exports.smartDeposit = smartDeposit;
|
|
1164
2640
|
exports.smartRedeem = smartRedeem;
|
|
2641
|
+
exports.submitActions = submitActions;
|
|
2642
|
+
exports.vetoActions = vetoActions;
|
|
2643
|
+
exports.waitForCompose = waitForCompose;
|
|
1165
2644
|
exports.withdrawAssets = withdrawAssets;
|
|
1166
2645
|
//# sourceMappingURL=index.cjs.map
|
|
1167
2646
|
//# sourceMappingURL=index.cjs.map
|