@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
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Contract, AbiCoder, zeroPadValue, Signer, Provider } from "ethers";
|
|
2
2
|
import { ERC20_ABI, OFT_ABI, BRIDGE_ABI, LZ_ENDPOINT_ABI } from "./abis";
|
|
3
3
|
import type { ContractTransactionReceipt } from "ethers";
|
|
4
|
+
import { EID_TO_CHAIN_ID, OFT_ROUTES, createChainProvider } from "./chains";
|
|
5
|
+
import { detectStargateOft } from "./utils";
|
|
6
|
+
import { OMNI_FACTORY_ADDRESS } from "./topology";
|
|
4
7
|
|
|
5
8
|
/** LZ Endpoint V2 address — same on all EVM chains */
|
|
6
9
|
const LZ_ENDPOINT = "0x1a44076050125825900e736c501f859c50fe728c";
|
|
@@ -309,3 +312,208 @@ export async function executeCompose(
|
|
|
309
312
|
|
|
310
313
|
return { receipt };
|
|
311
314
|
}
|
|
315
|
+
|
|
316
|
+
// ---------------------------------------------------------------------------
|
|
317
|
+
// Compose data types and waitForCompose
|
|
318
|
+
// ---------------------------------------------------------------------------
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Data needed to execute a pending LZ compose on the hub chain.
|
|
322
|
+
* Returned by `depositFromSpoke` when the OFT is a Stargate V2 pool.
|
|
323
|
+
* The SDK user must call `executeCompose()` with this data as TX2 on the hub.
|
|
324
|
+
*/
|
|
325
|
+
export interface ComposeData {
|
|
326
|
+
/** LZ Endpoint address on the hub chain */
|
|
327
|
+
endpoint: string
|
|
328
|
+
/** The OFT/pool address that sent the compose (Stargate pool on hub) — resolved by waitForCompose */
|
|
329
|
+
from: string
|
|
330
|
+
/** MoreVaultsComposer address on the hub */
|
|
331
|
+
to: string
|
|
332
|
+
/** LayerZero GUID from the original OFT.send() */
|
|
333
|
+
guid: string
|
|
334
|
+
/** Compose index (default 0) */
|
|
335
|
+
index: number
|
|
336
|
+
/** Full compose message bytes — resolved by waitForCompose from ComposeSent event */
|
|
337
|
+
message: string
|
|
338
|
+
/** Whether this is a Stargate OFT (2-TX flow) */
|
|
339
|
+
isStargate: boolean
|
|
340
|
+
/** Hub chain ID */
|
|
341
|
+
hubChainId: number
|
|
342
|
+
/** Block number on hub chain right before depositFromSpoke TX — used to bound event scan */
|
|
343
|
+
hubBlockStart: bigint
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Minimal ABIs for helper functions used only in this file */
|
|
347
|
+
const FACTORY_COMPOSER_ABI_MIN = [
|
|
348
|
+
"function vaultComposer(address _vault) view returns (address)",
|
|
349
|
+
] as const;
|
|
350
|
+
|
|
351
|
+
const COMPOSER_SHARE_OFT_ABI = [
|
|
352
|
+
"function SHARE_OFT() view returns (address)",
|
|
353
|
+
] as const;
|
|
354
|
+
|
|
355
|
+
const OFT_PEERS_ABI = [
|
|
356
|
+
"function peers(uint32 eid) view returns (bytes32)",
|
|
357
|
+
] as const;
|
|
358
|
+
|
|
359
|
+
const OFT_TOKEN_ABI = [
|
|
360
|
+
"function token() view returns (address)",
|
|
361
|
+
] as const;
|
|
362
|
+
|
|
363
|
+
const OFT_QUOTE_OFT_ABI = [
|
|
364
|
+
"function quoteOFT(tuple(uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd) sendParam) view returns (tuple(uint256 minAmountLD, uint256 maxAmountLD), tuple(int256 feeAmountLD, string description)[], tuple(uint256 amountSentLD, uint256 amountReceivedLD))",
|
|
365
|
+
] as const;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Wait for a pending compose to appear in the LZ Endpoint's composeQueue on the hub chain.
|
|
369
|
+
*
|
|
370
|
+
* After `depositFromSpoke` sends tokens via Stargate, the LZ network delivers the message
|
|
371
|
+
* to the hub chain. The endpoint stores the compose hash in `composeQueue` and emits
|
|
372
|
+
* a `ComposeSent` event with the full message bytes.
|
|
373
|
+
*
|
|
374
|
+
* Strategy: scan ComposeSent events on the LZ Endpoint starting from `hubBlockStart`
|
|
375
|
+
* (captured by `depositFromSpoke` right before TX1). We scan forward in 500-block chunks,
|
|
376
|
+
* matching by composer address and receiver in the message body.
|
|
377
|
+
*
|
|
378
|
+
* @param hubProvider Read-only provider on the HUB chain
|
|
379
|
+
* @param composeData Partial compose data (includes hubBlockStart, to, guid)
|
|
380
|
+
* @param receiver Receiver address to match in the compose message
|
|
381
|
+
* @param pollIntervalMs Polling interval (default 20s)
|
|
382
|
+
* @param timeoutMs Timeout (default 30 min)
|
|
383
|
+
* @returns Complete ComposeData ready for executeCompose
|
|
384
|
+
*/
|
|
385
|
+
export async function waitForCompose(
|
|
386
|
+
hubProvider: Provider,
|
|
387
|
+
composeData: ComposeData,
|
|
388
|
+
receiver: string,
|
|
389
|
+
pollIntervalMs = 20_000,
|
|
390
|
+
timeoutMs = 1_800_000,
|
|
391
|
+
): Promise<ComposeData> {
|
|
392
|
+
const deadline = Date.now() + timeoutMs
|
|
393
|
+
const composer = composeData.to.toLowerCase()
|
|
394
|
+
const endpoint = composeData.endpoint
|
|
395
|
+
const receiverNeedle = receiver.replace(/^0x/, '').toLowerCase()
|
|
396
|
+
const startBlock = composeData.hubBlockStart
|
|
397
|
+
|
|
398
|
+
// Collect Stargate OFT addresses on the hub chain
|
|
399
|
+
const hubChainId = composeData.hubChainId
|
|
400
|
+
const candidateAddresses: string[] = []
|
|
401
|
+
for (const chainMap of Object.values(OFT_ROUTES)) {
|
|
402
|
+
const entry = (chainMap as Record<number, { oft: string; token: string }>)[hubChainId]
|
|
403
|
+
if (entry) candidateAddresses.push(entry.oft.toLowerCase())
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Filter to Stargate addresses on-chain
|
|
407
|
+
const stargateChecks = await Promise.all(
|
|
408
|
+
candidateAddresses.map(async (addr) => ({
|
|
409
|
+
addr,
|
|
410
|
+
isSg: await detectStargateOft(hubProvider, addr),
|
|
411
|
+
})),
|
|
412
|
+
)
|
|
413
|
+
const knownFromAddresses = stargateChecks.filter((c) => c.isSg).map((c) => c.addr)
|
|
414
|
+
|
|
415
|
+
// ComposeSent event ABI for getLogs
|
|
416
|
+
const endpointContract = new Contract(endpoint, LZ_ENDPOINT_ABI, hubProvider)
|
|
417
|
+
|
|
418
|
+
// ComposeSent event topic
|
|
419
|
+
const COMPOSE_SENT_TOPIC = "0x0c68e6a0b0fb0f33c52455a8da89b21fc640a3dd4a1b21d9bfcc8aeee4a43e84"
|
|
420
|
+
|
|
421
|
+
let attempt = 0
|
|
422
|
+
let scannedUpTo = startBlock - 1n
|
|
423
|
+
|
|
424
|
+
while (Date.now() < deadline) {
|
|
425
|
+
attempt++
|
|
426
|
+
const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1000)
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
const currentBlock = BigInt(await hubProvider.getBlockNumber())
|
|
430
|
+
const chunkSize = 500n
|
|
431
|
+
let from = scannedUpTo + 1n
|
|
432
|
+
|
|
433
|
+
while (from <= currentBlock) {
|
|
434
|
+
const chunkEnd = from + chunkSize > currentBlock ? currentBlock : from + chunkSize
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
const logs = await hubProvider.getLogs({
|
|
438
|
+
address: endpoint,
|
|
439
|
+
topics: [COMPOSE_SENT_TOPIC],
|
|
440
|
+
fromBlock: `0x${from.toString(16)}`,
|
|
441
|
+
toBlock: `0x${chunkEnd.toString(16)}`,
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
for (const log of logs) {
|
|
445
|
+
// ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message)
|
|
446
|
+
// All params are non-indexed — decode from data
|
|
447
|
+
try {
|
|
448
|
+
const coder = AbiCoder.defaultAbiCoder()
|
|
449
|
+
const decoded = coder.decode(
|
|
450
|
+
['address', 'address', 'bytes32', 'uint16', 'bytes'],
|
|
451
|
+
log.data,
|
|
452
|
+
)
|
|
453
|
+
const logFrom = (decoded[0] as string).toLowerCase()
|
|
454
|
+
const logTo = (decoded[1] as string).toLowerCase()
|
|
455
|
+
const logGuid = decoded[2] as string
|
|
456
|
+
const logIndex = Number(decoded[3])
|
|
457
|
+
const logMessage = decoded[4] as string
|
|
458
|
+
|
|
459
|
+
if (
|
|
460
|
+
logTo === composer &&
|
|
461
|
+
logMessage.toLowerCase().includes(receiverNeedle)
|
|
462
|
+
) {
|
|
463
|
+
// Verify this compose is still pending in composeQueue
|
|
464
|
+
const hash: string = await endpointContract.composeQueue(
|
|
465
|
+
logFrom, composer, logGuid, logIndex,
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
|
|
469
|
+
console.log(`[${elapsed}s] Poll #${attempt} — compose found! (block ${log.blockNumber})`)
|
|
470
|
+
return {
|
|
471
|
+
...composeData,
|
|
472
|
+
from: decoded[0] as string,
|
|
473
|
+
to: composeData.to,
|
|
474
|
+
guid: logGuid,
|
|
475
|
+
index: logIndex,
|
|
476
|
+
message: logMessage,
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
} catch { /* decode failed — skip log */ }
|
|
481
|
+
}
|
|
482
|
+
} catch {
|
|
483
|
+
// Chunk failed (RPC limit) — break inner loop, will retry next poll
|
|
484
|
+
break
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
from = chunkEnd + 1n
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
scannedUpTo = currentBlock
|
|
491
|
+
} catch {
|
|
492
|
+
// getBlockNumber failed — retry next poll
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Also try composeQueue directly with spoke GUID (works when GUIDs match)
|
|
496
|
+
let guidMatchFound = false
|
|
497
|
+
for (const fromAddr of knownFromAddresses) {
|
|
498
|
+
try {
|
|
499
|
+
const hash: string = await endpointContract.composeQueue(
|
|
500
|
+
fromAddr, composer, composeData.guid, 0,
|
|
501
|
+
)
|
|
502
|
+
if (hash !== EMPTY_HASH && hash !== RECEIVED_HASH) {
|
|
503
|
+
console.log(`[${elapsed}s] Poll #${attempt} — composeQueue confirms pending (GUID match), re-scanning for message...`)
|
|
504
|
+
scannedUpTo = startBlock - 1n
|
|
505
|
+
guidMatchFound = true
|
|
506
|
+
}
|
|
507
|
+
} catch { /* continue */ }
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (!guidMatchFound) {
|
|
511
|
+
console.log(`[${elapsed}s] Poll #${attempt} — compose not found yet, waiting ${pollIntervalMs / 1000}s...`)
|
|
512
|
+
}
|
|
513
|
+
await new Promise(resolve => setTimeout(resolve, pollIntervalMs))
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
throw new Error(
|
|
517
|
+
`Timeout waiting for compose after ${timeoutMs / 60_000} min. Check LayerZero scan for composer ${composeData.to}.`,
|
|
518
|
+
)
|
|
519
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curator MulticallFacet write operations for the MoreVaults ethers.js v6 SDK.
|
|
3
|
+
*
|
|
4
|
+
* Provides typed helpers to submit, execute, and veto curator action batches
|
|
5
|
+
* on any MoreVaults diamond that has the MulticallFacet installed.
|
|
6
|
+
*
|
|
7
|
+
* @module curatorMulticall
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Contract, Interface } from "ethers";
|
|
11
|
+
import type { Signer, ContractTransactionReceipt } from "ethers";
|
|
12
|
+
import {
|
|
13
|
+
MULTICALL_ABI,
|
|
14
|
+
DEX_ABI,
|
|
15
|
+
ERC7540_FACET_ABI,
|
|
16
|
+
ERC4626_FACET_ABI,
|
|
17
|
+
} from "./abis";
|
|
18
|
+
import type { CuratorAction, SubmitActionsResult } from "./types";
|
|
19
|
+
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
// Encoding helpers
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Encode a single typed CuratorAction into raw calldata bytes suitable for
|
|
26
|
+
* passing into `submitActions(bytes[] actionsData)`.
|
|
27
|
+
*
|
|
28
|
+
* The encoded bytes are the full ABI-encoded function call (4-byte selector +
|
|
29
|
+
* arguments) targeting the vault diamond itself — the MulticallFacet will
|
|
30
|
+
* call `address(this).call(actionsData[i])` for each entry.
|
|
31
|
+
*
|
|
32
|
+
* @param action A discriminated-union CuratorAction describing what to do
|
|
33
|
+
* @returns ABI-encoded calldata hex string
|
|
34
|
+
*/
|
|
35
|
+
export function encodeCuratorAction(action: CuratorAction): string {
|
|
36
|
+
switch (action.type) {
|
|
37
|
+
case 'swap': {
|
|
38
|
+
const iface = new Interface(DEX_ABI as unknown as string[]);
|
|
39
|
+
return iface.encodeFunctionData("executeSwap", [
|
|
40
|
+
{
|
|
41
|
+
targetContract: action.params.targetContract,
|
|
42
|
+
tokenIn: action.params.tokenIn,
|
|
43
|
+
tokenOut: action.params.tokenOut,
|
|
44
|
+
maxAmountIn: action.params.maxAmountIn,
|
|
45
|
+
minAmountOut: action.params.minAmountOut,
|
|
46
|
+
swapCallData: action.params.swapCallData,
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
case 'batchSwap': {
|
|
52
|
+
const iface = new Interface(DEX_ABI as unknown as string[]);
|
|
53
|
+
return iface.encodeFunctionData("executeBatchSwap", [
|
|
54
|
+
{
|
|
55
|
+
swaps: action.params.swaps.map((s) => ({
|
|
56
|
+
targetContract: s.targetContract,
|
|
57
|
+
tokenIn: s.tokenIn,
|
|
58
|
+
tokenOut: s.tokenOut,
|
|
59
|
+
maxAmountIn: s.maxAmountIn,
|
|
60
|
+
minAmountOut: s.minAmountOut,
|
|
61
|
+
swapCallData: s.swapCallData,
|
|
62
|
+
})),
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
case 'erc4626Deposit': {
|
|
68
|
+
const iface = new Interface(ERC4626_FACET_ABI as unknown as string[]);
|
|
69
|
+
return iface.encodeFunctionData("erc4626Deposit", [action.vault, action.assets]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
case 'erc4626Redeem': {
|
|
73
|
+
const iface = new Interface(ERC4626_FACET_ABI as unknown as string[]);
|
|
74
|
+
return iface.encodeFunctionData("erc4626Redeem", [action.vault, action.shares]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case 'erc7540RequestDeposit': {
|
|
78
|
+
const iface = new Interface(ERC7540_FACET_ABI as unknown as string[]);
|
|
79
|
+
return iface.encodeFunctionData("erc7540RequestDeposit", [action.vault, action.assets]);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case 'erc7540Deposit': {
|
|
83
|
+
const iface = new Interface(ERC7540_FACET_ABI as unknown as string[]);
|
|
84
|
+
return iface.encodeFunctionData("erc7540Deposit", [action.vault, action.assets]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case 'erc7540RequestRedeem': {
|
|
88
|
+
const iface = new Interface(ERC7540_FACET_ABI as unknown as string[]);
|
|
89
|
+
return iface.encodeFunctionData("erc7540RequestRedeem", [action.vault, action.shares]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case 'erc7540Redeem': {
|
|
93
|
+
const iface = new Interface(ERC7540_FACET_ABI as unknown as string[]);
|
|
94
|
+
return iface.encodeFunctionData("erc7540Redeem", [action.vault, action.shares]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
default: {
|
|
98
|
+
// TypeScript exhaustiveness check — this branch is never reached at runtime
|
|
99
|
+
const _exhaustive: never = action;
|
|
100
|
+
throw new Error(`[MoreVaults] Unknown CuratorAction type: ${(_exhaustive as any).type}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Encode an array of CuratorActions into a calldata array ready for
|
|
107
|
+
* `submitActions`.
|
|
108
|
+
*
|
|
109
|
+
* @param actions Array of typed CuratorAction objects
|
|
110
|
+
* @returns Array of ABI-encoded calldata hex strings
|
|
111
|
+
*/
|
|
112
|
+
export function buildCuratorBatch(actions: CuratorAction[]): string[] {
|
|
113
|
+
return actions.map(encodeCuratorAction);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
117
|
+
// Write operations
|
|
118
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Submit a batch of curator actions to the vault's MulticallFacet.
|
|
122
|
+
*
|
|
123
|
+
* When `timeLockPeriod == 0` the contract immediately executes the actions
|
|
124
|
+
* inside `submitActions` itself. When a timelock is configured the actions
|
|
125
|
+
* are queued and must be executed later with `executeActions`.
|
|
126
|
+
*
|
|
127
|
+
* After the write succeeds, reads `getCurrentNonce` to determine which nonce
|
|
128
|
+
* was assigned (nonce - 1 after the submit increments it).
|
|
129
|
+
*
|
|
130
|
+
* @param signer Signer with curator account attached
|
|
131
|
+
* @param vault Vault address (diamond proxy)
|
|
132
|
+
* @param actions Array of raw calldata bytes — use `buildCuratorBatch` to build
|
|
133
|
+
* @returns Receipt and the nonce assigned to this batch
|
|
134
|
+
*/
|
|
135
|
+
export async function submitActions(
|
|
136
|
+
signer: Signer,
|
|
137
|
+
vault: string,
|
|
138
|
+
actions: string[]
|
|
139
|
+
): Promise<SubmitActionsResult> {
|
|
140
|
+
const multicallContract = new Contract(vault, MULTICALL_ABI, signer);
|
|
141
|
+
|
|
142
|
+
const tx = await multicallContract.submitActions(actions);
|
|
143
|
+
const receipt: ContractTransactionReceipt = await tx.wait();
|
|
144
|
+
|
|
145
|
+
// Read the nonce that was assigned: the contract increments actionNonce after storing,
|
|
146
|
+
// so getCurrentNonce now returns (assignedNonce + 1). Subtract 1 to recover it.
|
|
147
|
+
const nextNonce = (await multicallContract.getCurrentNonce()) as bigint;
|
|
148
|
+
const nonce = nextNonce - 1n;
|
|
149
|
+
|
|
150
|
+
return { receipt, nonce };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Execute pending actions after their timelock period has expired.
|
|
155
|
+
*
|
|
156
|
+
* Can only be called when `block.timestamp >= pendingUntil`. The contract
|
|
157
|
+
* reverts with `ActionsStillPending` if the timelock has not expired.
|
|
158
|
+
*
|
|
159
|
+
* @param signer Signer with curator account attached
|
|
160
|
+
* @param vault Vault address (diamond proxy)
|
|
161
|
+
* @param nonce The action batch nonce to execute
|
|
162
|
+
* @returns Transaction receipt
|
|
163
|
+
*/
|
|
164
|
+
export async function executeActions(
|
|
165
|
+
signer: Signer,
|
|
166
|
+
vault: string,
|
|
167
|
+
nonce: bigint
|
|
168
|
+
): Promise<ContractTransactionReceipt> {
|
|
169
|
+
const multicallContract = new Contract(vault, MULTICALL_ABI, signer);
|
|
170
|
+
|
|
171
|
+
const tx = await multicallContract.executeActions(nonce);
|
|
172
|
+
return tx.wait() as Promise<ContractTransactionReceipt>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Guardian-only: cancel (veto) one or more pending action batches.
|
|
177
|
+
*
|
|
178
|
+
* Deletes the pending actions from storage, preventing them from ever being
|
|
179
|
+
* executed. Only the vault guardian can call this.
|
|
180
|
+
*
|
|
181
|
+
* @param signer Signer with guardian account attached
|
|
182
|
+
* @param vault Vault address (diamond proxy)
|
|
183
|
+
* @param nonces Array of action nonces to cancel
|
|
184
|
+
* @returns Transaction receipt
|
|
185
|
+
*/
|
|
186
|
+
export async function vetoActions(
|
|
187
|
+
signer: Signer,
|
|
188
|
+
vault: string,
|
|
189
|
+
nonces: bigint[]
|
|
190
|
+
): Promise<ContractTransactionReceipt> {
|
|
191
|
+
const multicallContract = new Contract(vault, MULTICALL_ABI, signer);
|
|
192
|
+
|
|
193
|
+
const tx = await multicallContract.vetoActions(nonces);
|
|
194
|
+
return tx.wait() as Promise<ContractTransactionReceipt>;
|
|
195
|
+
}
|