@oydual31/more-vaults-sdk 1.1.19 → 1.1.21
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 +25 -3
- package/dist/ethers/index.cjs.map +1 -1
- package/dist/ethers/index.js +25 -3
- package/dist/ethers/index.js.map +1 -1
- package/dist/react/index.cjs +5 -2
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +5 -2
- package/dist/react/index.js.map +1 -1
- package/dist/viem/index.cjs +23 -4
- package/dist/viem/index.cjs.map +1 -1
- package/dist/viem/index.js +23 -4
- package/dist/viem/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ethers/userHelpers.ts +27 -3
- package/src/ethers/utils.ts +23 -8
- package/src/viem/userHelpers.ts +27 -6
- package/src/viem/utils.ts +18 -7
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { Contract, Interface } from "ethers";
|
|
8
8
|
import type { Provider } from "ethers";
|
|
9
|
-
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI, METADATA_ABI } from "./abis";
|
|
9
|
+
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI, METADATA_ABI, VAULT_ANALYSIS_ABI } from "./abis";
|
|
10
10
|
import type { CrossChainRequestInfo } from "./types";
|
|
11
11
|
import { getVaultStatus } from "./utils";
|
|
12
12
|
import type { VaultStatus } from "./utils";
|
|
@@ -172,6 +172,7 @@ export async function canDeposit(
|
|
|
172
172
|
user: string
|
|
173
173
|
): Promise<DepositEligibility> {
|
|
174
174
|
const config = new Contract(vault, CONFIG_ABI, provider);
|
|
175
|
+
const analysis = new Contract(vault, VAULT_ANALYSIS_ABI, provider);
|
|
175
176
|
|
|
176
177
|
const isPaused = await (config.paused() as Promise<boolean>);
|
|
177
178
|
|
|
@@ -179,12 +180,35 @@ export async function canDeposit(
|
|
|
179
180
|
return { allowed: false, reason: "paused" };
|
|
180
181
|
}
|
|
181
182
|
|
|
182
|
-
//
|
|
183
|
+
// Check whitelist via getAvailableToDeposit before the capacity check.
|
|
184
|
+
// maxDeposit() reverts on cross-chain async hub vaults, so we cannot rely on a maxDeposit()
|
|
185
|
+
// revert as a whitelist signal — getAvailableToDeposit() is the authoritative per-user check.
|
|
186
|
+
let whitelistEnabled = false;
|
|
187
|
+
try {
|
|
188
|
+
whitelistEnabled = await (analysis.isDepositWhitelistEnabled() as Promise<boolean>);
|
|
189
|
+
} catch {
|
|
190
|
+
// Older vaults may not have this function
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (whitelistEnabled) {
|
|
194
|
+
let available = 0n;
|
|
195
|
+
try {
|
|
196
|
+
available = await (analysis.getAvailableToDeposit(user) as Promise<bigint>);
|
|
197
|
+
} catch {
|
|
198
|
+
// Revert on getAvailableToDeposit — treat as not whitelisted
|
|
199
|
+
return { allowed: false, reason: "not-whitelisted" };
|
|
200
|
+
}
|
|
201
|
+
if (available === 0n) {
|
|
202
|
+
return { allowed: false, reason: "not-whitelisted" };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// maxDeposit(user) can REVERT on vaults with whitelist/ACL (legacy vaults without
|
|
207
|
+
// getAvailableToDeposit) or on cross-chain async hubs. Treat any revert as not-whitelisted.
|
|
183
208
|
let maxDepositAmount: bigint;
|
|
184
209
|
try {
|
|
185
210
|
maxDepositAmount = await (config.maxDeposit(user) as Promise<bigint>);
|
|
186
211
|
} catch {
|
|
187
|
-
// Revert means the vault has whitelist/ACL and this user is not approved
|
|
188
212
|
return { allowed: false, reason: "not-whitelisted" };
|
|
189
213
|
}
|
|
190
214
|
|
package/src/ethers/utils.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { Contract, Interface, ZeroAddress } from "ethers";
|
|
8
8
|
import type { Provider, Signer } from "ethers";
|
|
9
|
-
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI } from "./abis";
|
|
9
|
+
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI, ADMIN_CONFIG_ABI } from "./abis";
|
|
10
10
|
import { MoreVaultsError, CCManagerNotConfiguredError, AsyncRequestTimeoutError } from "./errors";
|
|
11
11
|
|
|
12
12
|
// Minimal ABI for Stargate type detection
|
|
@@ -288,12 +288,13 @@ export async function getVaultStatus(
|
|
|
288
288
|
vault: string
|
|
289
289
|
): Promise<VaultStatus> {
|
|
290
290
|
const mc = new Contract(MULTICALL3_ADDRESS, MULTICALL3_ABI, provider);
|
|
291
|
-
const configIface
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
291
|
+
const configIface = new Interface(CONFIG_ABI as unknown as string[]);
|
|
292
|
+
const adminConfigIface = new Interface(ADMIN_CONFIG_ABI as unknown as string[]);
|
|
293
|
+
const bridgeIface = new Interface(BRIDGE_ABI as unknown as string[]);
|
|
294
|
+
const vaultIface = new Interface(VAULT_ABI as unknown as string[]);
|
|
295
|
+
const decimalsIface = new Interface(["function decimals() view returns (uint8)"]);
|
|
295
296
|
|
|
296
|
-
// ── Batch 1:
|
|
297
|
+
// ── Batch 1: 13 calls → 1 eth_call via Multicall3.aggregate3 ─────────────
|
|
297
298
|
const b1Calls = [
|
|
298
299
|
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("isHub") },
|
|
299
300
|
{ target: vault, allowFailure: false, callData: configIface.encodeFunctionData("paused") },
|
|
@@ -308,6 +309,8 @@ export async function getVaultStatus(
|
|
|
308
309
|
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("totalAssets") },
|
|
309
310
|
{ target: vault, allowFailure: false, callData: vaultIface.encodeFunctionData("totalSupply") },
|
|
310
311
|
{ target: vault, allowFailure: false, callData: decimalsIface.encodeFunctionData("decimals") },
|
|
312
|
+
// allowFailure=true: older vaults may not have depositCapacity
|
|
313
|
+
{ target: vault, allowFailure: true, callData: adminConfigIface.encodeFunctionData("depositCapacity") },
|
|
311
314
|
];
|
|
312
315
|
|
|
313
316
|
const b1: { success: boolean; returnData: string }[] = await mc.aggregate3.staticCall(b1Calls);
|
|
@@ -329,6 +332,9 @@ export async function getVaultStatus(
|
|
|
329
332
|
const decimalsRaw = decimalsIface.decodeFunctionResult("decimals", b1[11].returnData)[0];
|
|
330
333
|
const decimalsNum = Number(decimalsRaw);
|
|
331
334
|
const oneShare = 10n ** BigInt(decimalsNum);
|
|
335
|
+
const depositCapacity = b1[12].success
|
|
336
|
+
? adminConfigIface.decodeFunctionResult("depositCapacity", b1[12].returnData)[0] as bigint
|
|
337
|
+
: 0n;
|
|
332
338
|
|
|
333
339
|
// ── Batch 2: 2 calls → 1 eth_call (depends on underlying + decimals) ─────
|
|
334
340
|
const erc20Iface = new Interface(ERC20_ABI as unknown as string[]);
|
|
@@ -353,11 +359,20 @@ export async function getVaultStatus(
|
|
|
353
359
|
const depositAccessRestricted = maxDepositRaw === null && !isCrossChainAsync;
|
|
354
360
|
const effectiveCapacity: bigint = maxDepositRaw === null ? MAX_UINT256 : maxDepositRaw!;
|
|
355
361
|
|
|
362
|
+
// maxDeposit(address(0)) returns 0 in two distinct cases:
|
|
363
|
+
// 1. Vault is truly at capacity: depositCapacity > 0 && totalAssets >= depositCapacity
|
|
364
|
+
// 2. Whitelist is enabled and address(0) has no quota — but vault is NOT full
|
|
365
|
+
// Only set mode='full' for case 1. Case 2 should remain 'local'/'cross-chain-oracle'
|
|
366
|
+
// so that smartDeposit proceeds and preflightSync throws WhitelistQuotaExhaustedError.
|
|
367
|
+
const isTrulyFull = effectiveCapacity === 0n
|
|
368
|
+
&& !isCrossChainAsync
|
|
369
|
+
&& (depositCapacity > 0n && totalAssets >= depositCapacity);
|
|
370
|
+
|
|
356
371
|
// ── Derive mode ────────────────────────────────────────────────────────────
|
|
357
372
|
let mode: VaultMode;
|
|
358
373
|
if (isPaused) {
|
|
359
374
|
mode = "paused";
|
|
360
|
-
} else if (
|
|
375
|
+
} else if (isTrulyFull) {
|
|
361
376
|
mode = "full";
|
|
362
377
|
} else if (!isHub) {
|
|
363
378
|
mode = "local";
|
|
@@ -389,7 +404,7 @@ export async function getVaultStatus(
|
|
|
389
404
|
if (isPaused) {
|
|
390
405
|
issues.push("Vault is paused — no deposits or redeems are possible.");
|
|
391
406
|
}
|
|
392
|
-
if (
|
|
407
|
+
if (isTrulyFull) {
|
|
393
408
|
issues.push(
|
|
394
409
|
"Deposit capacity is full — increase depositCapacity via setDepositCapacity()."
|
|
395
410
|
);
|
package/src/viem/userHelpers.ts
CHANGED
|
@@ -209,6 +209,10 @@ export async function canDeposit(
|
|
|
209
209
|
allowFailure: false,
|
|
210
210
|
})
|
|
211
211
|
|
|
212
|
+
if (isPaused) {
|
|
213
|
+
return { allowed: false, reason: 'paused', whitelistEnabled: false }
|
|
214
|
+
}
|
|
215
|
+
|
|
212
216
|
// Read whitelist status (may revert on older vaults — default to false)
|
|
213
217
|
let whitelistEnabled = false
|
|
214
218
|
try {
|
|
@@ -221,18 +225,36 @@ export async function canDeposit(
|
|
|
221
225
|
// Older vaults may not have this function
|
|
222
226
|
}
|
|
223
227
|
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
// Check whitelist via getAvailableToDeposit BEFORE the isCrossChainAsync short-circuit.
|
|
229
|
+
// Cross-chain async hub vaults revert on maxDeposit(), so we cannot use a maxDeposit() revert
|
|
230
|
+
// as a whitelist signal — getAvailableToDeposit() is the authoritative per-user check.
|
|
231
|
+
if (whitelistEnabled) {
|
|
232
|
+
let available = 0n
|
|
233
|
+
try {
|
|
234
|
+
available = await publicClient.readContract({
|
|
235
|
+
address: v,
|
|
236
|
+
abi: VAULT_ANALYSIS_ABI,
|
|
237
|
+
functionName: 'getAvailableToDeposit',
|
|
238
|
+
args: [getAddress(user)],
|
|
239
|
+
}) as bigint
|
|
240
|
+
} catch {
|
|
241
|
+
// Revert on getAvailableToDeposit — treat as not whitelisted
|
|
242
|
+
return { allowed: false, reason: 'not-whitelisted', maxDeposit: 0n, whitelistEnabled }
|
|
243
|
+
}
|
|
244
|
+
if (available === 0n) {
|
|
245
|
+
return { allowed: false, reason: 'not-whitelisted', maxDeposit: 0n, whitelistEnabled }
|
|
246
|
+
}
|
|
226
247
|
}
|
|
227
248
|
|
|
228
|
-
// Cross-chain async hubs
|
|
229
|
-
//
|
|
249
|
+
// Cross-chain async hubs accept deposits via initVaultActionRequest, not ERC-4626.
|
|
250
|
+
// maxDeposit() reverts on these vaults — skip the capacity check.
|
|
230
251
|
const isCrossChainAsync = isHub && !oraclesEnabled
|
|
231
252
|
if (isCrossChainAsync) {
|
|
232
253
|
return { allowed: true, reason: 'ok', whitelistEnabled }
|
|
233
254
|
}
|
|
234
255
|
|
|
235
|
-
//
|
|
256
|
+
// For standard (ERC-4626) vaults: check remaining capacity via maxDeposit.
|
|
257
|
+
// A revert here catches legacy vaults that use maxDeposit as an ACL gate.
|
|
236
258
|
let maxDepositAmount: bigint
|
|
237
259
|
try {
|
|
238
260
|
maxDepositAmount = await publicClient.readContract({
|
|
@@ -242,7 +264,6 @@ export async function canDeposit(
|
|
|
242
264
|
args: [getAddress(user)],
|
|
243
265
|
})
|
|
244
266
|
} catch {
|
|
245
|
-
// Revert means the vault has whitelist/ACL and this user is not approved
|
|
246
267
|
return { allowed: false, reason: 'not-whitelisted', maxDeposit: 0n, whitelistEnabled }
|
|
247
268
|
}
|
|
248
269
|
|
package/src/viem/utils.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getAddress,
|
|
7
7
|
zeroAddress,
|
|
8
8
|
} from 'viem'
|
|
9
|
-
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI, METADATA_ABI } from './abis'
|
|
9
|
+
import { BRIDGE_ABI, CONFIG_ABI, ERC20_ABI, VAULT_ABI, METADATA_ABI, ADMIN_CONFIG_ABI } from './abis'
|
|
10
10
|
import type { CrossChainRequestInfo } from './types'
|
|
11
11
|
import { MoreVaultsError, CCManagerNotConfiguredError, AsyncRequestTimeoutError } from './errors.js'
|
|
12
12
|
import { getDefaultStorage, clearDepositFlow, type FlowStorage } from './flowStorage'
|
|
@@ -174,11 +174,12 @@ export async function getVaultStatus(
|
|
|
174
174
|
{ address: v, abi: CONFIG_ABI, functionName: 'getEscrow' },
|
|
175
175
|
{ address: v, abi: CONFIG_ABI, functionName: 'getWithdrawalQueueStatus' },
|
|
176
176
|
{ address: v, abi: CONFIG_ABI, functionName: 'getWithdrawalTimelock' },
|
|
177
|
-
{ address: v, abi: CONFIG_ABI,
|
|
178
|
-
{ address: v, abi: VAULT_ABI,
|
|
179
|
-
{ address: v, abi: VAULT_ABI,
|
|
180
|
-
{ address: v, abi: VAULT_ABI,
|
|
181
|
-
{ address: v, abi: METADATA_ABI,
|
|
177
|
+
{ address: v, abi: CONFIG_ABI, functionName: 'maxDeposit', args: [zeroAddress] },
|
|
178
|
+
{ address: v, abi: VAULT_ABI, functionName: 'asset' },
|
|
179
|
+
{ address: v, abi: VAULT_ABI, functionName: 'totalAssets' },
|
|
180
|
+
{ address: v, abi: VAULT_ABI, functionName: 'totalSupply' },
|
|
181
|
+
{ address: v, abi: METADATA_ABI, functionName: 'decimals' },
|
|
182
|
+
{ address: v, abi: ADMIN_CONFIG_ABI, functionName: 'depositCapacity' },
|
|
182
183
|
] as const,
|
|
183
184
|
allowFailure: true,
|
|
184
185
|
})
|
|
@@ -196,6 +197,7 @@ export async function getVaultStatus(
|
|
|
196
197
|
const totalAssets = b1[9].status === 'success' ? b1[9].result as bigint : 0n
|
|
197
198
|
const totalSupply = b1[10].status === 'success' ? b1[10].result as bigint : 0n
|
|
198
199
|
const decimals = b1[11].status === 'success' ? Number(b1[11].result) : 18
|
|
200
|
+
const depositCapacity = b1[12].status === 'success' ? b1[12].result as bigint : 0n
|
|
199
201
|
|
|
200
202
|
// ── Batch 2: depends on underlying + decimals from batch 1 ────────────────
|
|
201
203
|
const oneShare = 10n ** BigInt(decimals)
|
|
@@ -221,11 +223,20 @@ export async function getVaultStatus(
|
|
|
221
223
|
const depositAccessRestricted = maxDepositRaw === null && !isCrossChainAsync
|
|
222
224
|
const effectiveCapacity: bigint = (maxDepositRaw === null) ? MAX_UINT256 : maxDepositRaw
|
|
223
225
|
|
|
226
|
+
// maxDeposit(address(0)) returns 0 in two distinct cases:
|
|
227
|
+
// 1. Vault is truly at capacity: depositCapacity > 0 && totalAssets >= depositCapacity
|
|
228
|
+
// 2. Whitelist is enabled and address(0) has no quota — but vault is NOT full
|
|
229
|
+
// Only set mode='full' for case 1. Case 2 should remain 'local'/'cross-chain-oracle'
|
|
230
|
+
// so that smartDeposit proceeds and preflightSync throws WhitelistQuotaExhaustedError.
|
|
231
|
+
const isTrulyFull = effectiveCapacity === 0n
|
|
232
|
+
&& !isCrossChainAsync
|
|
233
|
+
&& (depositCapacity > 0n && totalAssets >= depositCapacity)
|
|
234
|
+
|
|
224
235
|
// ── Derive mode ────────────────────────────────────────────────────────────
|
|
225
236
|
let mode: VaultMode
|
|
226
237
|
if (isPaused) {
|
|
227
238
|
mode = 'paused'
|
|
228
|
-
} else if (
|
|
239
|
+
} else if (isTrulyFull) {
|
|
229
240
|
mode = 'full'
|
|
230
241
|
} else if (!isHub) {
|
|
231
242
|
mode = 'local'
|