@obolnetwork/obol-sdk 2.10.2 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/abi/BatchDeposit.js +120 -0
- package/dist/cjs/src/abi/Multicall3.js +253 -0
- package/dist/cjs/src/bytecodes.js +4 -4
- package/dist/cjs/src/constants.js +13 -7
- package/dist/cjs/src/eoa/eoa.js +48 -0
- package/dist/cjs/src/eoa/eoaHelpers.js +45 -1
- package/dist/cjs/src/index.js +2 -2
- package/dist/cjs/src/schema.js +83 -1
- package/dist/cjs/src/splits/splitHelpers.js +64 -19
- package/dist/cjs/src/splits/splits.js +54 -11
- package/dist/cjs/test/eoa/eoa.spec.js +75 -0
- package/dist/cjs/test/splits/splits.spec.js +84 -0
- package/dist/esm/package.json +1 -1
- package/dist/esm/src/abi/BatchDeposit.js +117 -0
- package/dist/esm/src/abi/Multicall3.js +250 -0
- package/dist/esm/src/bytecodes.js +3 -3
- package/dist/esm/src/constants.js +14 -8
- package/dist/esm/src/eoa/eoa.js +50 -2
- package/dist/esm/src/eoa/eoaHelpers.js +43 -0
- package/dist/esm/src/index.js +2 -2
- package/dist/esm/src/schema.js +82 -0
- package/dist/esm/src/splits/splitHelpers.js +61 -17
- package/dist/esm/src/splits/splits.js +56 -13
- package/dist/esm/test/eoa/eoa.spec.js +76 -1
- package/dist/esm/test/splits/splits.spec.js +85 -1
- package/dist/types/src/abi/BatchDeposit.d.ts +49 -0
- package/dist/types/src/abi/Multicall3.d.ts +37 -0
- package/dist/types/src/bytecodes.d.ts +3 -3
- package/dist/types/src/eoa/eoa.d.ts +34 -1
- package/dist/types/src/eoa/eoaHelpers.d.ts +15 -0
- package/dist/types/src/schema.d.ts +76 -0
- package/dist/types/src/splits/splitHelpers.d.ts +22 -1
- package/dist/types/src/splits/splits.d.ts +33 -1
- package/dist/types/src/types.d.ts +40 -1
- package/package.json +1 -1
- package/src/abi/BatchDeposit.ts +117 -0
- package/src/abi/Multicall3.ts +250 -0
- package/src/bytecodes.ts +3 -3
- package/src/constants.ts +16 -10
- package/src/eoa/eoa.ts +60 -2
- package/src/eoa/eoaHelpers.ts +68 -0
- package/src/index.ts +4 -4
- package/src/schema.ts +84 -0
- package/src/splits/splitHelpers.ts +99 -19
- package/src/splits/splits.ts +65 -15
- package/src/types.ts +43 -1
- package/dist/cjs/src/abi/Multicall.js +0 -148
- package/dist/esm/src/abi/Multicall.js +0 -145
- package/dist/types/src/abi/Multicall.d.ts +0 -35
- package/src/abi/Multicall.ts +0 -145
|
@@ -146,9 +146,9 @@ exports.CHAIN_CONFIGURATION = {
|
|
|
146
146
|
address: '0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE',
|
|
147
147
|
bytecode: bytecodes_1.MAINNET_SPLITMAIN_BYTECODE,
|
|
148
148
|
},
|
|
149
|
-
|
|
150
|
-
address: '
|
|
151
|
-
bytecode: bytecodes_1.
|
|
149
|
+
MULTICALL3_CONTRACT: {
|
|
150
|
+
address: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
|
151
|
+
bytecode: bytecodes_1.MAINNET_MULTICALL3_BYTECODE,
|
|
152
152
|
},
|
|
153
153
|
OWR_FACTORY_CONTRACT: {
|
|
154
154
|
address: '0x119acd7844cbdd5fc09b1c6a4408f490c8f7f522',
|
|
@@ -174,15 +174,18 @@ exports.CHAIN_CONFIGURATION = {
|
|
|
174
174
|
EOA_WITHDRAWAL_CONTRACT: {
|
|
175
175
|
address: '0x00000961Ef480Eb55e80D19ad83579A64c007002',
|
|
176
176
|
},
|
|
177
|
+
BATCH_DEPOSIT_CONTRACT: {
|
|
178
|
+
address: '0xcD7a6C118Ac8F6544BC5076F2D8Fb86D2C546756',
|
|
179
|
+
},
|
|
177
180
|
},
|
|
178
181
|
[types_1.FORK_MAPPING['0x01017000']]: {
|
|
179
182
|
SPLITMAIN_CONTRACT: {
|
|
180
183
|
address: '0xfC8a305728051367797DADE6Aa0344E0987f5286',
|
|
181
184
|
bytecode: bytecodes_1.HOLESKY_SPLITMAIN_BYTECODE,
|
|
182
185
|
},
|
|
183
|
-
|
|
186
|
+
MULTICALL3_CONTRACT: {
|
|
184
187
|
address: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
|
185
|
-
bytecode: bytecodes_1.
|
|
188
|
+
bytecode: bytecodes_1.HOLESKY_MULTICALL3_BYTECODE,
|
|
186
189
|
},
|
|
187
190
|
OWR_FACTORY_CONTRACT: {
|
|
188
191
|
address: '0xc0961353fcc43a99e3041db07ac646720e116256',
|
|
@@ -201,9 +204,9 @@ exports.CHAIN_CONFIGURATION = {
|
|
|
201
204
|
address: '0xc05ae267291705ac16F75283572294ed2a91CBc7',
|
|
202
205
|
bytecode: bytecodes_1.HOODI_SPLITMAIN_BYTECODE,
|
|
203
206
|
},
|
|
204
|
-
|
|
207
|
+
MULTICALL3_CONTRACT: {
|
|
205
208
|
address: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
|
206
|
-
bytecode: bytecodes_1.
|
|
209
|
+
bytecode: bytecodes_1.HOODI_MULTICALL3_BYTECODE,
|
|
207
210
|
},
|
|
208
211
|
OWR_FACTORY_CONTRACT: {
|
|
209
212
|
address: '0x9ff0c649d0bf5fe7efa4d72e94bed7302ed5c8d7',
|
|
@@ -229,6 +232,9 @@ exports.CHAIN_CONFIGURATION = {
|
|
|
229
232
|
EOA_WITHDRAWAL_CONTRACT: {
|
|
230
233
|
address: '0x00000961Ef480Eb55e80D19ad83579A64c007002',
|
|
231
234
|
},
|
|
235
|
+
BATCH_DEPOSIT_CONTRACT: {
|
|
236
|
+
address: '0x4c9506eE2fCd962f03022D9d8ebf6f7828abEfaf',
|
|
237
|
+
},
|
|
232
238
|
},
|
|
233
239
|
};
|
|
234
240
|
exports.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT = 1;
|
package/dist/cjs/src/eoa/eoa.js
CHANGED
|
@@ -79,5 +79,53 @@ class EOA {
|
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Deposits to batch deposit contract.
|
|
84
|
+
*
|
|
85
|
+
* This method allows depositing multiple validators to the Ethereum beacon chain
|
|
86
|
+
* using the Pier Two batch deposit contract for gas efficiency.
|
|
87
|
+
* Each deposit includes validator public key, withdrawal credentials, signature, and amount.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* **⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed
|
|
91
|
+
* and not pushed to version control.
|
|
92
|
+
*
|
|
93
|
+
* **⚠️ Gas Limit:** Due to EVM constraints, it is recommended to deposit in batches of up to 500 at a time.
|
|
94
|
+
*
|
|
95
|
+
* @param {EOADepositPayload} payload - Data needed to deposit to batch contract
|
|
96
|
+
* @returns {Promise<{txHashes: string[]}>} Array of transaction hashes for all batches
|
|
97
|
+
* @throws Will throw an error if the signer is not provided, contract is not configured, or the deposit fails
|
|
98
|
+
*
|
|
99
|
+
* An example of how to use deposit:
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const result = await client.eoa.deposit({
|
|
102
|
+
* deposits: [{
|
|
103
|
+
* pubKey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
104
|
+
* withdrawalCredentials: '0x1234567890123456789012345678901234567890',
|
|
105
|
+
* signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
106
|
+
* amount: '32000000000000000000' // 32 ETH in wei
|
|
107
|
+
* }]
|
|
108
|
+
* });
|
|
109
|
+
* console.log('Deposits completed:', result.txHashes);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
deposit(payload) {
|
|
113
|
+
var _a;
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
if (!this.signer) {
|
|
116
|
+
throw new Error('Signer is required in deposit');
|
|
117
|
+
}
|
|
118
|
+
const chainConfig = constants_1.CHAIN_CONFIGURATION[this.chainId];
|
|
119
|
+
if (!((_a = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.BATCH_DEPOSIT_CONTRACT) === null || _a === void 0 ? void 0 : _a.address)) {
|
|
120
|
+
throw new Error(`Batch deposit contract is not configured for chain ${this.chainId}`);
|
|
121
|
+
}
|
|
122
|
+
const validatedPayload = (0, ajv_1.validatePayload)(payload, schema_1.eoaDepositPayloadSchema);
|
|
123
|
+
return yield (0, eoaHelpers_1.submitEOABatchDeposit)({
|
|
124
|
+
deposits: validatedPayload.deposits,
|
|
125
|
+
batchDepositContractAddress: chainConfig.BATCH_DEPOSIT_CONTRACT.address,
|
|
126
|
+
signer: this.signer,
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
82
130
|
}
|
|
83
131
|
exports.EOA = EOA;
|
|
@@ -9,8 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.submitEOAWithdrawalRequest = void 0;
|
|
12
|
+
exports.submitEOABatchDeposit = exports.submitEOAWithdrawalRequest = void 0;
|
|
13
13
|
const constants_1 = require("../constants");
|
|
14
|
+
const ethers_1 = require("ethers");
|
|
15
|
+
const BatchDeposit_1 = require("../abi/BatchDeposit");
|
|
14
16
|
/**
|
|
15
17
|
* Helper function to submit withdrawal request for EOA
|
|
16
18
|
*/
|
|
@@ -35,3 +37,45 @@ function submitEOAWithdrawalRequest({ pubkey, allocation, withdrawalAddress, wit
|
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
39
|
exports.submitEOAWithdrawalRequest = submitEOAWithdrawalRequest;
|
|
40
|
+
/**
|
|
41
|
+
* Helper function to submit batch deposit request for EOA
|
|
42
|
+
*/
|
|
43
|
+
function submitEOABatchDeposit({ deposits, batchDepositContractAddress, signer, }) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
if (!deposits || deposits.length === 0) {
|
|
46
|
+
throw new Error('No deposits provided');
|
|
47
|
+
}
|
|
48
|
+
// Create contract instance
|
|
49
|
+
const batchDepositContract = new ethers_1.Contract(batchDepositContractAddress, BatchDeposit_1.BatchDepositContract.abi, signer);
|
|
50
|
+
const BATCH_SIZE = 500;
|
|
51
|
+
const txHashes = [];
|
|
52
|
+
try {
|
|
53
|
+
// Process deposits in batches of 500
|
|
54
|
+
for (let i = 0; i < deposits.length; i += BATCH_SIZE) {
|
|
55
|
+
const batchDeposits = deposits.slice(i, i + BATCH_SIZE);
|
|
56
|
+
// Calculate total value needed for this batch
|
|
57
|
+
const totalValue = batchDeposits.reduce((sum, deposit) => sum + BigInt(deposit.amount), BigInt(0));
|
|
58
|
+
// Prepare deposit data for this batch
|
|
59
|
+
const depositData = batchDeposits.map(deposit => ({
|
|
60
|
+
pubKey: deposit.pubKey,
|
|
61
|
+
withdrawalCredentials: deposit.withdrawalCredentials,
|
|
62
|
+
signature: deposit.signature,
|
|
63
|
+
amount: BigInt(deposit.amount),
|
|
64
|
+
}));
|
|
65
|
+
// Execute batch deposit for this batch
|
|
66
|
+
const tx = yield batchDepositContract.batchDeposit(depositData, {
|
|
67
|
+
value: totalValue,
|
|
68
|
+
});
|
|
69
|
+
const receipt = yield tx.wait();
|
|
70
|
+
if (receipt === null || receipt === void 0 ? void 0 : receipt.hash) {
|
|
71
|
+
txHashes.push(receipt.hash);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { txHashes };
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw new Error("Failed to submit batch deposit'}");
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
exports.submitEOABatchDeposit = submitEOABatchDeposit;
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -156,9 +156,9 @@ class Client extends base_js_1.Base {
|
|
|
156
156
|
throw new Error(`SPLITMAIN_CONTRACT is not configured for chain ${this.chainId}`);
|
|
157
157
|
}
|
|
158
158
|
const checkSplitMainAddress = yield (0, utils_js_1.isContractAvailable)(chainConfig.SPLITMAIN_CONTRACT.address, this.signer.provider, chainConfig.SPLITMAIN_CONTRACT.bytecode);
|
|
159
|
-
const
|
|
159
|
+
const checkMulticall3Address = yield (0, utils_js_1.isContractAvailable)(chainConfig.MULTICALL3_CONTRACT.address, this.signer.provider, chainConfig.MULTICALL3_CONTRACT.bytecode);
|
|
160
160
|
const checkOWRFactoryAddress = yield (0, utils_js_1.isContractAvailable)(chainConfig.OWR_FACTORY_CONTRACT.address, this.signer.provider, chainConfig.OWR_FACTORY_CONTRACT.bytecode);
|
|
161
|
-
if (!
|
|
161
|
+
if (!checkMulticall3Address ||
|
|
162
162
|
!checkSplitMainAddress ||
|
|
163
163
|
!checkOWRFactoryAddress) {
|
|
164
164
|
throw new Error(`Something isn not working as expected, check this issue with obol-sdk team on ${constants_js_1.OBOL_SDK_EMAIL}`);
|
package/dist/cjs/src/schema.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.eoaWithdrawalPayloadSchema = exports.ovmRequestWithdrawalPayloadSchema = exports.ovmTotalSplitPayloadSchema = exports.ovmRewardsSplitPayloadSchema = exports.ovmBaseSplitPayload = exports.rewardsSplitterPayloadSchema = exports.totalSplitterPayloadSchema = exports.definitionSchema = exports.operatorPayloadSchema = void 0;
|
|
3
|
+
exports.eoaDepositPayloadSchema = exports.ovmDepositPayloadSchema = exports.eoaWithdrawalPayloadSchema = exports.ovmRequestWithdrawalPayloadSchema = exports.ovmTotalSplitPayloadSchema = exports.ovmRewardsSplitPayloadSchema = exports.ovmBaseSplitPayload = exports.rewardsSplitterPayloadSchema = exports.totalSplitterPayloadSchema = exports.definitionSchema = exports.operatorPayloadSchema = void 0;
|
|
4
4
|
const ethers_1 = require("ethers");
|
|
5
5
|
const constants_1 = require("./constants");
|
|
6
6
|
const ajv_1 = require("./ajv");
|
|
@@ -258,3 +258,85 @@ exports.eoaWithdrawalPayloadSchema = {
|
|
|
258
258
|
},
|
|
259
259
|
required: ['pubkey', 'allocation', 'requiredFee'],
|
|
260
260
|
};
|
|
261
|
+
exports.ovmDepositPayloadSchema = {
|
|
262
|
+
type: 'object',
|
|
263
|
+
properties: {
|
|
264
|
+
ovmAddress: {
|
|
265
|
+
type: 'string',
|
|
266
|
+
pattern: '^0x[a-fA-F0-9]{40}$',
|
|
267
|
+
},
|
|
268
|
+
deposits: {
|
|
269
|
+
type: 'array',
|
|
270
|
+
minItems: 1,
|
|
271
|
+
items: {
|
|
272
|
+
type: 'object',
|
|
273
|
+
properties: {
|
|
274
|
+
pubkey: {
|
|
275
|
+
type: 'string',
|
|
276
|
+
pattern: '^0x[a-fA-F0-9]{96}$',
|
|
277
|
+
},
|
|
278
|
+
withdrawal_credentials: {
|
|
279
|
+
type: 'string',
|
|
280
|
+
pattern: '^0x[a-fA-F0-9]{64}$',
|
|
281
|
+
description: '32 bytes withdrawal credentials',
|
|
282
|
+
},
|
|
283
|
+
signature: {
|
|
284
|
+
type: 'string',
|
|
285
|
+
pattern: '^0x[a-fA-F0-9]{192}$',
|
|
286
|
+
description: '96 bytes signature (190 hex chars + 0x prefix)',
|
|
287
|
+
},
|
|
288
|
+
deposit_data_root: {
|
|
289
|
+
type: 'string',
|
|
290
|
+
pattern: '^0x[a-fA-F0-9]{64}$', // 32 bytes = 64 hex chars + 0x prefix
|
|
291
|
+
},
|
|
292
|
+
amount: {
|
|
293
|
+
type: 'string',
|
|
294
|
+
pattern: '^[0-9]+$',
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
required: [
|
|
298
|
+
'pubkey',
|
|
299
|
+
'withdrawal_credentials',
|
|
300
|
+
'signature',
|
|
301
|
+
'deposit_data_root',
|
|
302
|
+
'amount',
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
required: ['ovmAddress', 'deposits'],
|
|
308
|
+
};
|
|
309
|
+
exports.eoaDepositPayloadSchema = {
|
|
310
|
+
type: 'object',
|
|
311
|
+
properties: {
|
|
312
|
+
deposits: {
|
|
313
|
+
type: 'array',
|
|
314
|
+
minItems: 1,
|
|
315
|
+
items: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
properties: {
|
|
318
|
+
pubKey: {
|
|
319
|
+
type: 'string',
|
|
320
|
+
pattern: '^0x[a-fA-F0-9]{96}$',
|
|
321
|
+
},
|
|
322
|
+
withdrawalCredentials: {
|
|
323
|
+
type: 'string',
|
|
324
|
+
pattern: '^0x[a-fA-F0-9]{64}$',
|
|
325
|
+
description: '32 bytes withdrawal credentials',
|
|
326
|
+
},
|
|
327
|
+
signature: {
|
|
328
|
+
type: 'string',
|
|
329
|
+
pattern: '^0x[a-fA-F0-9]{192}$',
|
|
330
|
+
description: '96 bytes signature (190 hex chars + 0x prefix)',
|
|
331
|
+
},
|
|
332
|
+
amount: {
|
|
333
|
+
type: 'string',
|
|
334
|
+
pattern: '^[0-9]+$',
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
required: ['pubKey', 'withdrawalCredentials', 'signature', 'amount'],
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
required: ['deposits'],
|
|
342
|
+
};
|
|
@@ -9,14 +9,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.requestWithdrawalFromOVM = exports.deployOVMAndSplitV2 = exports.deployOVMContract = exports.isSplitV2Deployed = exports.predictSplitV2Address = exports.formatRecipientsForSplitV2 = exports.
|
|
12
|
+
exports.depositWithMulticall3 = exports.requestWithdrawalFromOVM = exports.deployOVMAndSplitV2 = exports.deployOVMContract = exports.isSplitV2Deployed = exports.predictSplitV2Address = exports.formatRecipientsForSplitV2 = exports.multicall3 = exports.getOWRTranches = exports.deploySplitterAndOWRContracts = exports.deploySplitterContract = exports.handleDeployOWRAndSplitter = exports.predictSplitterAddress = exports.formatSplitRecipients = void 0;
|
|
13
13
|
const ethers_1 = require("ethers");
|
|
14
14
|
const OWR_1 = require("../abi/OWR");
|
|
15
15
|
const OVMFactory_1 = require("../abi/OVMFactory");
|
|
16
16
|
const SplitMain_1 = require("../abi/SplitMain");
|
|
17
|
-
const Multicall_1 = require("../abi/Multicall");
|
|
18
17
|
const constants_1 = require("../constants");
|
|
19
18
|
const splitV2FactoryAbi_1 = require("../abi/splitV2FactoryAbi");
|
|
19
|
+
const Multicall3_1 = require("../abi/Multicall3");
|
|
20
20
|
const splitMainContractInterface = new ethers_1.Interface(SplitMain_1.splitMainEthereumAbi);
|
|
21
21
|
const owrFactoryContractInterface = new ethers_1.Interface(OWR_1.OWRFactoryContract.abi);
|
|
22
22
|
const ovmFactoryContractInterface = new ethers_1.Interface(OVMFactory_1.OVMFactoryContract.abi);
|
|
@@ -130,7 +130,7 @@ const handleDeployOWRAndSplitter = ({ signer, isSplitterDeployed, predictedSplit
|
|
|
130
130
|
splitterAddress = result.splitterAddress;
|
|
131
131
|
}
|
|
132
132
|
catch (error) {
|
|
133
|
-
throw new Error(`Failed to deploy both splitter and OWR contracts: ${(_e = error.message) !== null && _e !== void 0 ? _e : '
|
|
133
|
+
throw new Error(`Failed to deploy both splitter and OWR contracts: ${(_e = error.message) !== null && _e !== void 0 ? _e : 'Multicall3 contract deployment failed'}`);
|
|
134
134
|
}
|
|
135
135
|
return {
|
|
136
136
|
withdrawal_address: owrAddress,
|
|
@@ -249,7 +249,7 @@ const deploySplitterAndOWRContracts = ({ owrArgs, splitterArgs, signer, chainId,
|
|
|
249
249
|
target: getChainConfig(chainId).OWR_FACTORY_CONTRACT.address,
|
|
250
250
|
callData: owrTxData,
|
|
251
251
|
});
|
|
252
|
-
const executeMultiCalls = yield (0, exports.
|
|
252
|
+
const executeMultiCalls = yield (0, exports.multicall3)(executeCalls, signer, chainId);
|
|
253
253
|
const splitAddressData = (_s = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[0]) === null || _s === void 0 ? void 0 : _s.topics[1];
|
|
254
254
|
const formattedSplitterAddress = '0x' + (splitAddressData === null || splitAddressData === void 0 ? void 0 : splitAddressData.slice(26, 66));
|
|
255
255
|
const owrAddressData = (_t = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[1]) === null || _t === void 0 ? void 0 : _t.topics[1];
|
|
@@ -291,42 +291,42 @@ const getOWRTranches = ({ owrAddress, signer, }) => __awaiter(void 0, void 0, vo
|
|
|
291
291
|
}
|
|
292
292
|
});
|
|
293
293
|
exports.getOWRTranches = getOWRTranches;
|
|
294
|
-
const
|
|
294
|
+
const multicall3 = (calls, signer, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
295
295
|
var _w, _x, _y;
|
|
296
296
|
try {
|
|
297
297
|
const chainConfig = getChainConfig(chainId);
|
|
298
|
-
const
|
|
299
|
-
const
|
|
298
|
+
const multicall3Address = chainConfig.MULTICALL3_CONTRACT.address;
|
|
299
|
+
const multiCall3ContractInstance = new ethers_1.Contract(multicall3Address, Multicall3_1.MultiCall3Contract.abi, signer);
|
|
300
300
|
let tx;
|
|
301
301
|
try {
|
|
302
|
-
tx = yield
|
|
302
|
+
tx = yield multiCall3ContractInstance.aggregate(calls);
|
|
303
303
|
}
|
|
304
304
|
catch (error) {
|
|
305
|
-
throw new Error(`Failed to submit
|
|
305
|
+
throw new Error(`Failed to submit multicall3 transaction: ${(_w = error.message) !== null && _w !== void 0 ? _w : 'Transaction submission failed'}`);
|
|
306
306
|
}
|
|
307
307
|
let receipt;
|
|
308
308
|
try {
|
|
309
309
|
receipt = yield tx.wait();
|
|
310
310
|
}
|
|
311
311
|
catch (error) {
|
|
312
|
-
throw new Error(`
|
|
312
|
+
throw new Error(`Multicall3 transaction failed or was reverted: ${(_x = error.message) !== null && _x !== void 0 ? _x : 'Transaction execution failed'}`);
|
|
313
313
|
}
|
|
314
314
|
if (!receipt) {
|
|
315
|
-
throw new Error('
|
|
315
|
+
throw new Error('Multicall3 transaction succeeded but no receipt was returned');
|
|
316
316
|
}
|
|
317
317
|
return receipt;
|
|
318
318
|
}
|
|
319
319
|
catch (error) {
|
|
320
320
|
// Re-throw if it's already our custom error
|
|
321
321
|
if (error.message.includes('Failed to') ||
|
|
322
|
-
error.message.includes('
|
|
322
|
+
error.message.includes('Multicall3 transaction')) {
|
|
323
323
|
throw error;
|
|
324
324
|
}
|
|
325
325
|
// Handle unexpected errors
|
|
326
|
-
throw new Error(`Unexpected error in
|
|
326
|
+
throw new Error(`Unexpected error in multicall3: ${(_y = error.message) !== null && _y !== void 0 ? _y : 'Unknown error during multicall3 execution'}`);
|
|
327
327
|
}
|
|
328
328
|
});
|
|
329
|
-
exports.
|
|
329
|
+
exports.multicall3 = multicall3;
|
|
330
330
|
const encodeCreateSplitTxData = (accounts, percentAllocations, distributorFee, controller) => {
|
|
331
331
|
return splitMainContractInterface.encodeFunctionData('createSplit', [
|
|
332
332
|
accounts,
|
|
@@ -460,8 +460,8 @@ const deployOVMAndSplitV2 = ({ ovmArgs, rewardRecipients, isRewardsSplitterDeplo
|
|
|
460
460
|
target: chainConfig.OVM_FACTORY_CONTRACT.address,
|
|
461
461
|
callData: ovmTxData,
|
|
462
462
|
});
|
|
463
|
-
// Execute
|
|
464
|
-
const executeMultiCalls = yield (0, exports.
|
|
463
|
+
// Execute multicall3
|
|
464
|
+
const executeMultiCalls = yield (0, exports.multicall3)(executeCalls, signer, chainId);
|
|
465
465
|
// Extract addresses from events
|
|
466
466
|
let ovmAddress;
|
|
467
467
|
const logsCount = ((_7 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs) === null || _7 === void 0 ? void 0 : _7.length) || 0;
|
|
@@ -475,7 +475,7 @@ const deployOVMAndSplitV2 = ({ ovmArgs, rewardRecipients, isRewardsSplitterDeplo
|
|
|
475
475
|
ovmAddress = '0x' + ((_13 = (_12 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[7]) === null || _12 === void 0 ? void 0 : _12.topics[1]) === null || _13 === void 0 ? void 0 : _13.slice(26, 66));
|
|
476
476
|
}
|
|
477
477
|
if (!ovmAddress) {
|
|
478
|
-
throw new Error('Failed to extract contract addresses from
|
|
478
|
+
throw new Error('Failed to extract contract addresses from multicall3 events');
|
|
479
479
|
}
|
|
480
480
|
return ovmAddress;
|
|
481
481
|
}
|
|
@@ -508,7 +508,6 @@ const getChainConfig = (chainId) => {
|
|
|
508
508
|
* @returns Promise that resolves to the transaction hash
|
|
509
509
|
*/
|
|
510
510
|
const requestWithdrawalFromOVM = ({ ovmAddress, pubKeys, amounts, withdrawalFees, signer, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
511
|
-
var _15;
|
|
512
511
|
try {
|
|
513
512
|
// Convert string amounts to bigint
|
|
514
513
|
const bigintAmounts = amounts.map(amount => BigInt(amount));
|
|
@@ -520,7 +519,53 @@ const requestWithdrawalFromOVM = ({ ovmAddress, pubKeys, amounts, withdrawalFees
|
|
|
520
519
|
return { txHash: receipt.hash };
|
|
521
520
|
}
|
|
522
521
|
catch (error) {
|
|
523
|
-
|
|
522
|
+
const errorMessage = error instanceof Error ? error.message : 'Request withdrawal failed';
|
|
523
|
+
throw new Error(`Failed to request withdrawal from OVM: ${errorMessage}`);
|
|
524
524
|
}
|
|
525
525
|
});
|
|
526
526
|
exports.requestWithdrawalFromOVM = requestWithdrawalFromOVM;
|
|
527
|
+
/**
|
|
528
|
+
* Deposits to OVM contract using multicall3 for batch operations
|
|
529
|
+
* @param ovmAddress - The address of the OVM contract
|
|
530
|
+
* @param deposits - Array of deposit objects with all required parameters
|
|
531
|
+
* @param signer - The signer to use for the transaction
|
|
532
|
+
* @returns Promise that resolves to an array of transaction hashes
|
|
533
|
+
*/
|
|
534
|
+
const depositWithMulticall3 = ({ ovmAddress, deposits, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
535
|
+
try {
|
|
536
|
+
const ovmContract = new ethers_1.Contract(ovmAddress, OVMFactory_1.OVMContract.abi, signer);
|
|
537
|
+
const chainConfig = getChainConfig(chainId);
|
|
538
|
+
const multicall3Address = chainConfig.MULTICALL3_CONTRACT.address;
|
|
539
|
+
const multiCall3ContractInstance = new ethers_1.Contract(multicall3Address, Multicall3_1.MultiCall3Contract.abi, signer);
|
|
540
|
+
const BATCH_SIZE = 500;
|
|
541
|
+
const txHashes = [];
|
|
542
|
+
// Process deposits in batches of 500
|
|
543
|
+
for (let i = 0; i < deposits.length; i += BATCH_SIZE) {
|
|
544
|
+
const batchDeposits = deposits.slice(i, i + BATCH_SIZE);
|
|
545
|
+
// Use Multicall3 aggregate3Value (payable per-call)
|
|
546
|
+
const callsWithValue = batchDeposits.map(deposit => ({
|
|
547
|
+
target: ovmAddress,
|
|
548
|
+
allowFailure: false,
|
|
549
|
+
callData: ovmContract.interface.encodeFunctionData('deposit', [
|
|
550
|
+
deposit.pubkey,
|
|
551
|
+
deposit.withdrawal_credentials,
|
|
552
|
+
deposit.signature,
|
|
553
|
+
deposit.deposit_data_root,
|
|
554
|
+
]),
|
|
555
|
+
value: BigInt(deposit.amount),
|
|
556
|
+
}));
|
|
557
|
+
const totalBatchValue = callsWithValue.reduce((sum, c) => sum + c.value, BigInt(0));
|
|
558
|
+
const tx = yield multiCall3ContractInstance.aggregate3Value(callsWithValue, { value: totalBatchValue });
|
|
559
|
+
const receipt = yield tx.wait();
|
|
560
|
+
if (receipt === null || receipt === void 0 ? void 0 : receipt.hash) {
|
|
561
|
+
txHashes.push(receipt.hash);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return { txHashes };
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
const errorMessage = error instanceof Error ? error.message : 'Deposit failed';
|
|
568
|
+
throw new Error(`Failed to deposit to OVM with multicall3: ${errorMessage}`);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
exports.depositWithMulticall3 = depositWithMulticall3;
|
|
@@ -65,21 +65,21 @@ class ObolSplits {
|
|
|
65
65
|
}
|
|
66
66
|
const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
|
|
67
67
|
const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
|
|
68
|
-
const
|
|
68
|
+
const multiCall3Config = chainConfig.MULTICALL3_CONTRACT;
|
|
69
69
|
if (!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.address) ||
|
|
70
70
|
!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.bytecode) ||
|
|
71
71
|
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.address) ||
|
|
72
72
|
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.bytecode) ||
|
|
73
|
-
!(
|
|
74
|
-
!(
|
|
73
|
+
!(multiCall3Config === null || multiCall3Config === void 0 ? void 0 : multiCall3Config.address) ||
|
|
74
|
+
!(multiCall3Config === null || multiCall3Config === void 0 ? void 0 : multiCall3Config.bytecode)) {
|
|
75
75
|
throw new Error(`Contracts configuration is incomplete for chain ${this.chainId}`);
|
|
76
76
|
}
|
|
77
77
|
const checkOVMFactoryContract = yield (0, utils_1.isContractAvailable)(ovmFactoryConfig.address, this.provider, ovmFactoryConfig.bytecode);
|
|
78
78
|
const checkSplitV2FactoryContract = yield (0, utils_1.isContractAvailable)(splitV2FactoryConfig.address, this.provider, splitV2FactoryConfig.bytecode);
|
|
79
|
-
const
|
|
79
|
+
const checkMultiCall3Contract = yield (0, utils_1.isContractAvailable)(multiCall3Config.address, this.provider, multiCall3Config.bytecode);
|
|
80
80
|
if (!checkOVMFactoryContract ||
|
|
81
81
|
!checkSplitV2FactoryContract ||
|
|
82
|
-
!
|
|
82
|
+
!checkMultiCall3Contract) {
|
|
83
83
|
throw new Error(`Splitter contract is not deployed or available on chain ${this.chainId}`);
|
|
84
84
|
}
|
|
85
85
|
const retroActiveFundingRecipient = {
|
|
@@ -181,21 +181,21 @@ class ObolSplits {
|
|
|
181
181
|
}
|
|
182
182
|
const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
|
|
183
183
|
const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
|
|
184
|
-
const
|
|
184
|
+
const multiCall3Config = chainConfig.MULTICALL3_CONTRACT;
|
|
185
185
|
if (!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.address) ||
|
|
186
186
|
!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.bytecode) ||
|
|
187
187
|
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.address) ||
|
|
188
188
|
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.bytecode) ||
|
|
189
|
-
!(
|
|
190
|
-
!(
|
|
189
|
+
!(multiCall3Config === null || multiCall3Config === void 0 ? void 0 : multiCall3Config.address) ||
|
|
190
|
+
!(multiCall3Config === null || multiCall3Config === void 0 ? void 0 : multiCall3Config.bytecode)) {
|
|
191
191
|
throw new Error(`Contracts configuration is incomplete for chain ${this.chainId}`);
|
|
192
192
|
}
|
|
193
193
|
const checkOVMFactoryContract = yield (0, utils_1.isContractAvailable)(ovmFactoryConfig.address, this.provider, ovmFactoryConfig.bytecode);
|
|
194
194
|
const checkSplitV2FactoryContract = yield (0, utils_1.isContractAvailable)(splitV2FactoryConfig.address, this.provider, splitV2FactoryConfig.bytecode);
|
|
195
|
-
const
|
|
195
|
+
const checkMultiCall3Contract = yield (0, utils_1.isContractAvailable)(multiCall3Config.address, this.provider, multiCall3Config.bytecode);
|
|
196
196
|
if (!checkOVMFactoryContract ||
|
|
197
197
|
!checkSplitV2FactoryContract ||
|
|
198
|
-
!
|
|
198
|
+
!checkMultiCall3Contract) {
|
|
199
199
|
throw new Error(`Splitter contract is not deployed or available on chain ${this.chainId}`);
|
|
200
200
|
}
|
|
201
201
|
const retroActiveFundingRecipient = {
|
|
@@ -255,7 +255,7 @@ class ObolSplits {
|
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
257
|
else {
|
|
258
|
-
// Use
|
|
258
|
+
// Use multicall3 to deploy any contracts that aren't deployed
|
|
259
259
|
const ovmAddress = yield (0, splitHelpers_1.deployOVMAndSplitV2)({
|
|
260
260
|
ovmArgs: {
|
|
261
261
|
OVMOwnerAddress: validatedPayload.OVMOwnerAddress,
|
|
@@ -319,5 +319,48 @@ class ObolSplits {
|
|
|
319
319
|
});
|
|
320
320
|
});
|
|
321
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Deposits to OVM contract using multicall3 for batch operations.
|
|
324
|
+
*
|
|
325
|
+
* This method allows depositing to an OVM contract using multicall3 for efficient batch processing.
|
|
326
|
+
* Each deposit includes validator public key, withdrawal credentials, signature, deposit data root, and amount.
|
|
327
|
+
*
|
|
328
|
+
* @remarks
|
|
329
|
+
* **⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed
|
|
330
|
+
* and not pushed to version control.
|
|
331
|
+
*
|
|
332
|
+
* @param {OVMDepositPayload} payload - Data needed to deposit to OVM
|
|
333
|
+
* @returns {Promise<{txHashes: string[]}>} Array of transaction hashes for all batches
|
|
334
|
+
* @throws Will throw an error if the signer is not provided, OVM address is invalid, or the deposit fails
|
|
335
|
+
*
|
|
336
|
+
* An example of how to use deposit:
|
|
337
|
+
* ```typescript
|
|
338
|
+
* const result = await client.splits.deposit({
|
|
339
|
+
* ovmAddress: '0x1234567890123456789012345678901234567890',
|
|
340
|
+
* deposits: [{
|
|
341
|
+
* pubkey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
342
|
+
* withdrawal_credentials: '0x1234567890123456789012345678901234567890',
|
|
343
|
+
* signature: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
344
|
+
* deposit_data_root: '0x1234567890123456789012345678901234567890123456789012345678901234',
|
|
345
|
+
* amount: '32000000000000000000' // 32 ETH in wei
|
|
346
|
+
* }]
|
|
347
|
+
* });
|
|
348
|
+
* console.log('Deposits completed:', result.txHashes);
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
deposit(payload) {
|
|
352
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
353
|
+
if (!this.signer) {
|
|
354
|
+
throw new Error('Signer is required in deposit');
|
|
355
|
+
}
|
|
356
|
+
const validatedPayload = (0, ajv_1.validatePayload)(payload, schema_1.ovmDepositPayloadSchema);
|
|
357
|
+
return yield (0, splitHelpers_1.depositWithMulticall3)({
|
|
358
|
+
ovmAddress: validatedPayload.ovmAddress,
|
|
359
|
+
deposits: validatedPayload.deposits,
|
|
360
|
+
signer: this.signer,
|
|
361
|
+
chainId: this.chainId,
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
322
365
|
}
|
|
323
366
|
exports.ObolSplits = ObolSplits;
|
|
@@ -14,6 +14,7 @@ const eoaHelpers_1 = require("../../src/eoa/eoaHelpers");
|
|
|
14
14
|
// Mock the helper function
|
|
15
15
|
jest.mock('../../src/eoa/eoaHelpers', () => ({
|
|
16
16
|
submitEOAWithdrawalRequest: jest.fn(),
|
|
17
|
+
submitEOABatchDeposit: jest.fn(),
|
|
17
18
|
}));
|
|
18
19
|
describe('EOA', () => {
|
|
19
20
|
let eoa;
|
|
@@ -95,4 +96,78 @@ describe('EOA', () => {
|
|
|
95
96
|
expect(result).toEqual(mockResult);
|
|
96
97
|
}));
|
|
97
98
|
});
|
|
99
|
+
describe('deposit', () => {
|
|
100
|
+
const mockDeposits = [
|
|
101
|
+
{
|
|
102
|
+
pubKey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
103
|
+
withdrawalCredentials: '0x1234567890123456789012345678901234567890123456789012345678901234',
|
|
104
|
+
signature: '0x121234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012000000000000000000',
|
|
105
|
+
amount: '32000000000000000000', // 32 ETH in wei
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
it('should successfully deposit to batch contract', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
+
const mockPayload = {
|
|
110
|
+
deposits: mockDeposits,
|
|
111
|
+
};
|
|
112
|
+
const mockResult = {
|
|
113
|
+
txHashes: [
|
|
114
|
+
'0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
eoaHelpers_1.submitEOABatchDeposit.mockResolvedValue(mockResult);
|
|
118
|
+
const result = yield eoa.deposit(mockPayload);
|
|
119
|
+
expect(eoaHelpers_1.submitEOABatchDeposit).toHaveBeenCalledWith({
|
|
120
|
+
deposits: mockDeposits,
|
|
121
|
+
batchDepositContractAddress: '0xcD7a6C118Ac8F6544BC5076F2D8Fb86D2C546756',
|
|
122
|
+
signer: mockSigner,
|
|
123
|
+
});
|
|
124
|
+
expect(result).toEqual(mockResult);
|
|
125
|
+
}));
|
|
126
|
+
it('should throw error when signer is not provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
127
|
+
const eoaWithoutSigner = new eoa_1.EOA(undefined, 1, mockProvider);
|
|
128
|
+
const mockPayload = {
|
|
129
|
+
deposits: mockDeposits,
|
|
130
|
+
};
|
|
131
|
+
yield expect(eoaWithoutSigner.deposit(mockPayload)).rejects.toThrow('Signer is required in deposit');
|
|
132
|
+
}));
|
|
133
|
+
it('should throw error when batch deposit contract is not configured for chain', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
134
|
+
const eoaUnsupportedChain = new eoa_1.EOA(mockSigner, 999, mockProvider);
|
|
135
|
+
const mockPayload = {
|
|
136
|
+
deposits: mockDeposits,
|
|
137
|
+
};
|
|
138
|
+
yield expect(eoaUnsupportedChain.deposit(mockPayload)).rejects.toThrow('Batch deposit contract is not configured for chain 999');
|
|
139
|
+
}));
|
|
140
|
+
it('should handle multiple deposits', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
const multipleDeposits = [
|
|
142
|
+
{
|
|
143
|
+
pubKey: '0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
144
|
+
withdrawalCredentials: '0x1234567890123456789012345678901234567890123456789012345678901234',
|
|
145
|
+
signature: '0x121234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012000000000000000000',
|
|
146
|
+
amount: '32000000000000000000',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
pubKey: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdcd',
|
|
150
|
+
withdrawalCredentials: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
151
|
+
signature: '0x121234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012000000000000000000',
|
|
152
|
+
amount: '16000000000000000000',
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
const mockPayload = {
|
|
156
|
+
deposits: multipleDeposits,
|
|
157
|
+
};
|
|
158
|
+
const mockResult = {
|
|
159
|
+
txHashes: [
|
|
160
|
+
'0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
eoaHelpers_1.submitEOABatchDeposit.mockResolvedValue(mockResult);
|
|
164
|
+
const result = yield eoa.deposit(mockPayload);
|
|
165
|
+
expect(eoaHelpers_1.submitEOABatchDeposit).toHaveBeenCalledWith({
|
|
166
|
+
deposits: multipleDeposits,
|
|
167
|
+
batchDepositContractAddress: '0xcD7a6C118Ac8F6544BC5076F2D8Fb86D2C546756',
|
|
168
|
+
signer: mockSigner,
|
|
169
|
+
});
|
|
170
|
+
expect(result).toEqual(mockResult);
|
|
171
|
+
}));
|
|
172
|
+
});
|
|
98
173
|
});
|