@morpho-org/bundler-sdk-viem 2.2.1-next.0 → 3.0.0-next.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/lib/BundlerAction.d.ts +177 -107
- package/lib/BundlerAction.js +1032 -403
- package/lib/abis.d.ts +3062 -0
- package/lib/abis.js +2095 -0
- package/lib/actions.d.ts +0 -1
- package/lib/actions.js +92 -163
- package/lib/errors.d.ts +4 -1
- package/lib/errors.js +6 -0
- package/lib/operations.js +61 -53
- package/lib/types/actions.d.ts +73 -27
- package/package.json +11 -11
package/lib/actions.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ import type { Action, ActionBundle, BundlerOperation, TransactionRequirement } f
|
|
|
5
5
|
export declare const APPROVE_ONLY_ONCE_TOKENS: Partial<Record<ChainId, Address[]>>;
|
|
6
6
|
export declare const encodeOperation: (operation: BundlerOperation, dataBefore: MaybeDraft<SimulationState>, supportsSignature?: boolean, index?: number) => {
|
|
7
7
|
dataAfter: MaybeDraft<SimulationState>;
|
|
8
|
-
value: bigint;
|
|
9
8
|
actions: Action[];
|
|
10
9
|
requirements: {
|
|
11
10
|
signatures: import("./types/actions.js").SignatureRequirement[];
|
package/lib/actions.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { encodeFunctionData, erc20Abi, maxUint256, verifyTypedData, zeroAddress, } from "viem";
|
|
2
|
-
import { ChainId, MathLib, NATIVE_ADDRESS, convexWrapperTokens, erc20WrapperTokens, getChainAddresses, } from "@morpho-org/blue-sdk";
|
|
2
|
+
import { ChainId, MathLib, NATIVE_ADDRESS, convexWrapperTokens, erc20WrapperTokens, getChainAddresses, getUnwrappedToken, } from "@morpho-org/blue-sdk";
|
|
3
3
|
import { Time, getValue } from "@morpho-org/morpho-ts";
|
|
4
4
|
import { simulateOperation, } from "@morpho-org/simulation-sdk";
|
|
5
5
|
import { blueAbi, getAuthorizationTypedData, getDaiPermitTypedData, getPermit2PermitTypedData, getPermitTypedData, } from "@morpho-org/blue-sdk-viem";
|
|
6
6
|
import { signTypedData } from "viem/actions";
|
|
7
7
|
import BundlerAction from "./BundlerAction.js";
|
|
8
|
-
import { baseBundlerAbi } from "./abis.js";
|
|
9
8
|
export const APPROVE_ONLY_ONCE_TOKENS = {
|
|
10
9
|
[ChainId.EthMainnet]: [
|
|
11
10
|
"0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
|
|
@@ -19,14 +18,14 @@ const MAX_TOKEN_APPROVALS = {
|
|
|
19
18
|
};
|
|
20
19
|
const encodeErc20Approval = (token, sender, spender, amount, data) => {
|
|
21
20
|
const { chainId } = data;
|
|
22
|
-
const { morpho,
|
|
21
|
+
const { morpho, bundler3: { generalAdapter1 }, permit2, } = getChainAddresses(chainId);
|
|
23
22
|
amount = MathLib.min(amount, MAX_TOKEN_APPROVALS[chainId]?.[token] ?? maxUint256);
|
|
24
23
|
const txRequirements = [];
|
|
25
24
|
if (APPROVE_ONLY_ONCE_TOKENS[chainId]?.includes(token)) {
|
|
26
25
|
const contract = spender === morpho
|
|
27
26
|
? "morpho"
|
|
28
|
-
: spender ===
|
|
29
|
-
? "
|
|
27
|
+
: spender === generalAdapter1
|
|
28
|
+
? "bundler3.generalAdapter1"
|
|
30
29
|
: spender === permit2
|
|
31
30
|
? "permit2"
|
|
32
31
|
: undefined;
|
|
@@ -66,8 +65,7 @@ const encodeErc20Approval = (token, sender, spender, amount, data) => {
|
|
|
66
65
|
export const encodeOperation = (operation, dataBefore, supportsSignature = true, index = 0) => {
|
|
67
66
|
const { chainId } = dataBefore;
|
|
68
67
|
const deadline = Time.timestamp() + Time.s.from.h(24n);
|
|
69
|
-
const { morpho,
|
|
70
|
-
let value = 0n;
|
|
68
|
+
const { morpho, bundler3: { bundler3, generalAdapter1 }, permit2, wNative, dai, wstEth, stEth, } = getChainAddresses(chainId);
|
|
71
69
|
const actions = [];
|
|
72
70
|
const requirements = {
|
|
73
71
|
signatures: [],
|
|
@@ -101,7 +99,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
101
99
|
const ownerData = dataBefore.getUser(owner);
|
|
102
100
|
const authorization = {
|
|
103
101
|
authorizer: owner,
|
|
104
|
-
authorized:
|
|
102
|
+
authorized: generalAdapter1,
|
|
105
103
|
isAuthorized: true,
|
|
106
104
|
deadline,
|
|
107
105
|
nonce: ownerData.morphoNonce,
|
|
@@ -114,10 +112,11 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
114
112
|
requirements.signatures.push({
|
|
115
113
|
action,
|
|
116
114
|
async sign(client, account = client.account) {
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
let signature = action.args[1];
|
|
116
|
+
if (signature != null)
|
|
117
|
+
return signature;
|
|
119
118
|
const typedData = getAuthorizationTypedData(authorization, chainId);
|
|
120
|
-
|
|
119
|
+
signature = await signTypedData(client, {
|
|
121
120
|
...typedData,
|
|
122
121
|
account,
|
|
123
122
|
});
|
|
@@ -134,13 +133,13 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
134
133
|
// Signatures are not supported, fallback to standard approval.
|
|
135
134
|
requirements.txs.push({
|
|
136
135
|
type: "morphoSetAuthorization",
|
|
137
|
-
args: [
|
|
136
|
+
args: [generalAdapter1, true],
|
|
138
137
|
tx: {
|
|
139
138
|
to: morpho,
|
|
140
139
|
data: encodeFunctionData({
|
|
141
140
|
abi: blueAbi,
|
|
142
141
|
functionName: "setAuthorization",
|
|
143
|
-
args: [
|
|
142
|
+
args: [generalAdapter1, true],
|
|
144
143
|
}),
|
|
145
144
|
},
|
|
146
145
|
});
|
|
@@ -166,20 +165,20 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
166
165
|
const action = address === dai
|
|
167
166
|
? {
|
|
168
167
|
type: "permitDai",
|
|
169
|
-
args: [nonce, deadline, true, null],
|
|
168
|
+
args: [sender, nonce, deadline, true, null, spender],
|
|
170
169
|
}
|
|
171
170
|
: {
|
|
172
171
|
type: "permit",
|
|
173
|
-
args: [address, amount, deadline, null],
|
|
172
|
+
args: [sender, address, amount, deadline, null, spender],
|
|
174
173
|
};
|
|
175
174
|
actions.push(action);
|
|
176
175
|
const tokenData = dataBefore.getToken(address);
|
|
177
176
|
requirements.signatures.push({
|
|
178
177
|
action,
|
|
179
178
|
async sign(client, account = client.account) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
let signature = action.args[4];
|
|
180
|
+
if (signature != null)
|
|
181
|
+
return signature; // action is already signed
|
|
183
182
|
if (address === dai) {
|
|
184
183
|
const typedData = getDaiPermitTypedData({
|
|
185
184
|
owner: sender,
|
|
@@ -217,7 +216,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
217
216
|
signature,
|
|
218
217
|
});
|
|
219
218
|
}
|
|
220
|
-
return (action.args[
|
|
219
|
+
return (action.args[4] = signature);
|
|
221
220
|
},
|
|
222
221
|
});
|
|
223
222
|
break;
|
|
@@ -235,6 +234,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
235
234
|
const action = {
|
|
236
235
|
type: "approve2",
|
|
237
236
|
args: [
|
|
237
|
+
sender,
|
|
238
238
|
{
|
|
239
239
|
details: {
|
|
240
240
|
token: address,
|
|
@@ -242,7 +242,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
242
242
|
nonce: Number(nonce),
|
|
243
243
|
expiration: Number(expiration),
|
|
244
244
|
},
|
|
245
|
-
spender:
|
|
245
|
+
spender: bundler3,
|
|
246
246
|
sigDeadline: deadline,
|
|
247
247
|
},
|
|
248
248
|
null,
|
|
@@ -252,9 +252,10 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
252
252
|
requirements.signatures.push({
|
|
253
253
|
action,
|
|
254
254
|
async sign(client, account = client.account) {
|
|
255
|
-
const { details, spender, sigDeadline } = action.args[
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
const { details, spender, sigDeadline } = action.args[1];
|
|
256
|
+
let signature = action.args[2];
|
|
257
|
+
if (signature != null)
|
|
258
|
+
return signature; // action is already signed
|
|
258
259
|
const typedData = getPermit2PermitTypedData({
|
|
259
260
|
spender,
|
|
260
261
|
allowance: details.amount,
|
|
@@ -263,7 +264,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
263
264
|
deadline: sigDeadline,
|
|
264
265
|
expiration: details.expiration,
|
|
265
266
|
}, chainId);
|
|
266
|
-
|
|
267
|
+
signature = await signTypedData(client, {
|
|
267
268
|
...typedData,
|
|
268
269
|
account,
|
|
269
270
|
});
|
|
@@ -272,87 +273,52 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
272
273
|
address: sender, // Verify against the permit's owner.
|
|
273
274
|
signature,
|
|
274
275
|
});
|
|
275
|
-
return (action.args[
|
|
276
|
+
return (action.args[2] = signature);
|
|
276
277
|
},
|
|
277
278
|
});
|
|
278
279
|
break;
|
|
279
280
|
}
|
|
280
281
|
// Signatures are not supported, fallback to standard approval.
|
|
281
|
-
requirements.txs.push(...encodeErc20Approval(address, sender,
|
|
282
|
+
requirements.txs.push(...encodeErc20Approval(address, sender, generalAdapter1, amount, dataBefore));
|
|
282
283
|
break;
|
|
283
284
|
}
|
|
284
285
|
case "Erc20_Transfer": {
|
|
285
286
|
const { amount, from, to } = operation.args;
|
|
286
|
-
|
|
287
|
-
if (from === bundler) {
|
|
288
|
-
if (address === NATIVE_ADDRESS) {
|
|
289
|
-
actions.push({
|
|
290
|
-
type: "nativeTransfer",
|
|
291
|
-
args: [to, amount],
|
|
292
|
-
});
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
287
|
+
if (address === NATIVE_ADDRESS) {
|
|
295
288
|
actions.push({
|
|
296
|
-
type: "
|
|
297
|
-
args: [
|
|
289
|
+
type: "nativeTransfer",
|
|
290
|
+
args: [from, to, amount],
|
|
298
291
|
});
|
|
299
292
|
break;
|
|
300
293
|
}
|
|
301
|
-
//
|
|
302
|
-
if (
|
|
303
|
-
// Native token transfer is added to the call value (thus batched at the start of the bundle).
|
|
304
|
-
if (address === NATIVE_ADDRESS) {
|
|
305
|
-
value += amount;
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
294
|
+
// Output transfer from the bundler.
|
|
295
|
+
if (from === generalAdapter1) {
|
|
308
296
|
actions.push({
|
|
309
|
-
type: "
|
|
310
|
-
args: [address, amount],
|
|
297
|
+
type: "erc20Transfer",
|
|
298
|
+
args: [address, to, amount],
|
|
311
299
|
});
|
|
312
300
|
break;
|
|
313
301
|
}
|
|
314
|
-
|
|
302
|
+
actions.push({
|
|
303
|
+
type: "erc20TransferFrom",
|
|
304
|
+
args: [address, amount, to],
|
|
305
|
+
});
|
|
315
306
|
break;
|
|
316
307
|
}
|
|
317
308
|
case "Erc20_Transfer2": {
|
|
318
309
|
const { amount, from, to } = operation.args;
|
|
319
|
-
|
|
320
|
-
if (from === bundler) {
|
|
321
|
-
if (address === NATIVE_ADDRESS) {
|
|
322
|
-
actions.push({
|
|
323
|
-
type: "nativeTransfer",
|
|
324
|
-
args: [to, amount],
|
|
325
|
-
});
|
|
326
|
-
break;
|
|
327
|
-
}
|
|
328
|
-
actions.push({
|
|
329
|
-
type: "erc20Transfer",
|
|
330
|
-
args: [address, to, amount],
|
|
331
|
-
});
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
// Input transfer2 to the bundler.
|
|
335
|
-
if (to === bundler) {
|
|
336
|
-
// Native token transfer is added to the call value (thus batched at the start of the bundle).
|
|
337
|
-
if (address === NATIVE_ADDRESS) {
|
|
338
|
-
value += amount;
|
|
339
|
-
break;
|
|
340
|
-
}
|
|
341
|
-
if (supportsSignature) {
|
|
342
|
-
actions.push({
|
|
343
|
-
type: "transferFrom2",
|
|
344
|
-
args: [address, amount],
|
|
345
|
-
});
|
|
346
|
-
break;
|
|
347
|
-
}
|
|
348
|
-
// Signatures are not supported, fallback to standard transfer.
|
|
310
|
+
if (supportsSignature) {
|
|
349
311
|
actions.push({
|
|
350
|
-
type: "
|
|
351
|
-
args: [address, amount],
|
|
312
|
+
type: "transferFrom2",
|
|
313
|
+
args: [address, from, amount, to],
|
|
352
314
|
});
|
|
353
315
|
break;
|
|
354
316
|
}
|
|
355
|
-
//
|
|
317
|
+
// Signatures are not supported, fallback to standard transfer.
|
|
318
|
+
actions.push({
|
|
319
|
+
type: "erc20TransferFrom",
|
|
320
|
+
args: [address, amount, to],
|
|
321
|
+
});
|
|
356
322
|
break;
|
|
357
323
|
}
|
|
358
324
|
case "Erc20_Wrap": {
|
|
@@ -375,15 +341,18 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
375
341
|
case stEth: {
|
|
376
342
|
actions.push({
|
|
377
343
|
type: "stakeEth",
|
|
378
|
-
args: [amount,
|
|
344
|
+
args: [amount, MathLib.MAX_UINT_256, zeroAddress],
|
|
379
345
|
});
|
|
380
346
|
break;
|
|
381
347
|
}
|
|
382
348
|
default: {
|
|
383
349
|
if (erc20WrapperTokens[chainId].has(address)) {
|
|
350
|
+
const underlying = getUnwrappedToken(address, chainId);
|
|
351
|
+
if (underlying == null)
|
|
352
|
+
throw Error(`unknown wrapped token: ${address}`);
|
|
384
353
|
actions.push({
|
|
385
354
|
type: "erc20WrapperDepositFor",
|
|
386
|
-
args: [address, amount],
|
|
355
|
+
args: [address, underlying, amount],
|
|
387
356
|
});
|
|
388
357
|
break;
|
|
389
358
|
}
|
|
@@ -423,21 +392,17 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
423
392
|
break;
|
|
424
393
|
}
|
|
425
394
|
case "Blue_Supply": {
|
|
426
|
-
const { id, assets = 0n, shares = 0n, onBehalf } = operation.args;
|
|
427
|
-
const { params } = dataBefore.getMarket(id);
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
? dataAfter.getPosition(onBehalf, id).supplyShares -
|
|
431
|
-
dataBefore.getPosition(onBehalf, id).supplyShares
|
|
432
|
-
: dataAfter.getHolding(sender, params.loanToken).balance -
|
|
433
|
-
dataBefore.getHolding(sender, params.loanToken).balance;
|
|
395
|
+
const { id, assets = 0n, shares = 0n, onBehalf, slippage = 0n, } = operation.args;
|
|
396
|
+
const { params, totalSupplyAssets, totalSupplyShares } = dataBefore.getMarket(id);
|
|
397
|
+
const maxSharePrice = (totalSupplyAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
|
|
398
|
+
totalSupplyShares;
|
|
434
399
|
actions.push({
|
|
435
400
|
type: "morphoSupply",
|
|
436
401
|
args: [
|
|
437
402
|
params,
|
|
438
403
|
assets,
|
|
439
404
|
shares,
|
|
440
|
-
|
|
405
|
+
maxSharePrice,
|
|
441
406
|
onBehalf,
|
|
442
407
|
callbackBundle?.actions ?? [],
|
|
443
408
|
],
|
|
@@ -445,51 +410,39 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
445
410
|
break;
|
|
446
411
|
}
|
|
447
412
|
case "Blue_Withdraw": {
|
|
448
|
-
const { id, assets = 0n, shares = 0n,
|
|
449
|
-
const { params } = dataBefore.getMarket(id);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
? dataBefore.getPosition(onBehalf, id).supplyShares -
|
|
453
|
-
dataAfter.getPosition(onBehalf, id).supplyShares
|
|
454
|
-
: dataBefore.getHolding(sender, params.loanToken).balance -
|
|
455
|
-
dataAfter.getHolding(sender, params.loanToken).balance;
|
|
413
|
+
const { id, assets = 0n, shares = 0n, receiver, slippage = 0n, } = operation.args;
|
|
414
|
+
const { params, totalSupplyAssets, totalSupplyShares } = dataBefore.getMarket(id);
|
|
415
|
+
const minSharePrice = (totalSupplyAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
|
|
416
|
+
totalSupplyShares;
|
|
456
417
|
actions.push({
|
|
457
418
|
type: "morphoWithdraw",
|
|
458
|
-
args: [params, assets, shares,
|
|
419
|
+
args: [params, assets, shares, minSharePrice, receiver],
|
|
459
420
|
});
|
|
460
421
|
break;
|
|
461
422
|
}
|
|
462
423
|
case "Blue_Borrow": {
|
|
463
|
-
const { id, assets = 0n, shares = 0n,
|
|
464
|
-
const { params } = dataBefore.getMarket(id);
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
? dataAfter.getPosition(onBehalf, id).borrowShares -
|
|
468
|
-
dataBefore.getPosition(onBehalf, id).borrowShares
|
|
469
|
-
: dataAfter.getHolding(sender, params.loanToken).balance -
|
|
470
|
-
dataBefore.getHolding(sender, params.loanToken).balance;
|
|
424
|
+
const { id, assets = 0n, shares = 0n, receiver, slippage = 0n, } = operation.args;
|
|
425
|
+
const { params, totalBorrowAssets, totalBorrowShares } = dataBefore.getMarket(id);
|
|
426
|
+
const minSharePrice = (totalBorrowAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
|
|
427
|
+
totalBorrowShares;
|
|
471
428
|
actions.push({
|
|
472
429
|
type: "morphoBorrow",
|
|
473
|
-
args: [params, assets, shares,
|
|
430
|
+
args: [params, assets, shares, minSharePrice, receiver],
|
|
474
431
|
});
|
|
475
432
|
break;
|
|
476
433
|
}
|
|
477
434
|
case "Blue_Repay": {
|
|
478
|
-
const { id, assets = 0n, shares = 0n, onBehalf } = operation.args;
|
|
479
|
-
const { params } = dataBefore.getMarket(id);
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
? dataBefore.getPosition(onBehalf, id).borrowShares -
|
|
483
|
-
dataAfter.getPosition(onBehalf, id).borrowShares
|
|
484
|
-
: dataBefore.getHolding(sender, params.loanToken).balance -
|
|
485
|
-
dataAfter.getHolding(sender, params.loanToken).balance;
|
|
435
|
+
const { id, assets = 0n, shares = 0n, onBehalf, slippage = 0n, } = operation.args;
|
|
436
|
+
const { params, totalBorrowAssets, totalBorrowShares } = dataBefore.getMarket(id);
|
|
437
|
+
const maxSharePrice = (totalBorrowAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
|
|
438
|
+
totalBorrowShares;
|
|
486
439
|
actions.push({
|
|
487
440
|
type: "morphoRepay",
|
|
488
441
|
args: [
|
|
489
442
|
params,
|
|
490
443
|
assets,
|
|
491
444
|
shares,
|
|
492
|
-
|
|
445
|
+
maxSharePrice,
|
|
493
446
|
onBehalf,
|
|
494
447
|
callbackBundle?.actions ?? [],
|
|
495
448
|
],
|
|
@@ -500,9 +453,12 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
500
453
|
const { id, assets, onBehalf } = operation.args;
|
|
501
454
|
const { params } = dataBefore.getMarket(id);
|
|
502
455
|
if (convexWrapperTokens[chainId].has(params.collateralToken)) {
|
|
456
|
+
const underlying = getUnwrappedToken(address, chainId);
|
|
457
|
+
if (underlying == null)
|
|
458
|
+
throw Error(`unknown wrapped token: ${address}`);
|
|
503
459
|
actions.push({
|
|
504
460
|
type: "erc20WrapperDepositFor",
|
|
505
|
-
args: [params.collateralToken, assets],
|
|
461
|
+
args: [params.collateralToken, underlying, assets],
|
|
506
462
|
});
|
|
507
463
|
break;
|
|
508
464
|
}
|
|
@@ -522,61 +478,46 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
522
478
|
break;
|
|
523
479
|
}
|
|
524
480
|
case "MetaMorpho_Deposit": {
|
|
525
|
-
const { assets = 0n, shares = 0n, owner } = operation.args;
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
481
|
+
const { assets = 0n, shares = 0n, owner, slippage = 0n } = operation.args;
|
|
482
|
+
const vault = dataBefore.getVault(address);
|
|
483
|
+
const maxSharePrice = (vault.totalAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
|
|
484
|
+
vault.totalSupply;
|
|
485
|
+
if (shares === 0n)
|
|
530
486
|
actions.push({
|
|
531
487
|
type: "erc4626Deposit",
|
|
532
|
-
args: [address, assets,
|
|
488
|
+
args: [address, assets, maxSharePrice, owner],
|
|
533
489
|
});
|
|
534
|
-
|
|
535
|
-
else {
|
|
536
|
-
const vaultConfig = dataBefore.getVault(address);
|
|
537
|
-
// Already takes slippage into account.
|
|
538
|
-
const expectedAssets = dataBefore.getHolding(sender, vaultConfig.asset).balance -
|
|
539
|
-
dataAfter.getHolding(sender, vaultConfig.asset).balance;
|
|
490
|
+
else
|
|
540
491
|
actions.push({
|
|
541
492
|
type: "erc4626Mint",
|
|
542
|
-
args: [address, shares,
|
|
493
|
+
args: [address, shares, maxSharePrice, owner],
|
|
543
494
|
});
|
|
544
|
-
}
|
|
545
495
|
break;
|
|
546
496
|
}
|
|
547
497
|
case "MetaMorpho_Withdraw": {
|
|
548
|
-
const { assets = 0n, shares = 0n, owner, receiver } = operation.args;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
498
|
+
const { assets = 0n, shares = 0n, owner, receiver, slippage = 0n, } = operation.args;
|
|
499
|
+
const vault = dataBefore.getVault(address);
|
|
500
|
+
const minSharePrice = (vault.totalAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
|
|
501
|
+
vault.totalSupply;
|
|
502
|
+
if (assets > 0n)
|
|
553
503
|
actions.push({
|
|
554
504
|
type: "erc4626Withdraw",
|
|
555
|
-
args: [address, assets,
|
|
505
|
+
args: [address, assets, minSharePrice, receiver, owner],
|
|
556
506
|
});
|
|
557
|
-
|
|
558
|
-
else {
|
|
559
|
-
const vaultConfig = dataBefore.getVault(address);
|
|
560
|
-
// Already takes slippage into account.
|
|
561
|
-
const expectedAssets = dataAfter.getHolding(receiver, vaultConfig.asset).balance -
|
|
562
|
-
dataBefore.getHolding(receiver, vaultConfig.asset).balance;
|
|
507
|
+
else
|
|
563
508
|
actions.push({
|
|
564
509
|
type: "erc4626Redeem",
|
|
565
|
-
args: [address, shares,
|
|
510
|
+
args: [address, shares, minSharePrice, receiver, owner],
|
|
566
511
|
});
|
|
567
|
-
}
|
|
568
512
|
break;
|
|
569
513
|
}
|
|
570
514
|
case "MetaMorpho_PublicReallocate": {
|
|
571
515
|
const { withdrawals, supplyMarketId } = operation.args;
|
|
572
|
-
if (publicAllocator == null)
|
|
573
|
-
throw Error(`unknown public allocator on chain ${chainId}`);
|
|
574
516
|
const { fee } = dataBefore.getVault(address).publicAllocatorConfig;
|
|
575
517
|
// Value is already accrued via another native input transfer.
|
|
576
518
|
actions.push({
|
|
577
519
|
type: "reallocateTo",
|
|
578
520
|
args: [
|
|
579
|
-
publicAllocator,
|
|
580
521
|
address,
|
|
581
522
|
fee,
|
|
582
523
|
withdrawals.map(({ id, assets }) => ({
|
|
@@ -591,15 +532,12 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
|
|
|
591
532
|
}
|
|
592
533
|
return {
|
|
593
534
|
dataAfter,
|
|
594
|
-
value,
|
|
595
535
|
actions,
|
|
596
536
|
requirements,
|
|
597
537
|
};
|
|
598
538
|
};
|
|
599
539
|
export function encodeBundle(operations, startData, supportsSignature = true) {
|
|
600
540
|
const { chainId } = startData;
|
|
601
|
-
const { bundler } = getChainAddresses(chainId);
|
|
602
|
-
let value = 0n;
|
|
603
541
|
const actions = [];
|
|
604
542
|
const requirements = {
|
|
605
543
|
signatures: [],
|
|
@@ -609,7 +547,6 @@ export function encodeBundle(operations, startData, supportsSignature = true) {
|
|
|
609
547
|
for (let index = 0; index < operations.length; ++index) {
|
|
610
548
|
const bundle = encodeOperation(operations[index], steps[index], supportsSignature, index);
|
|
611
549
|
steps.push(bundle.dataAfter);
|
|
612
|
-
value += bundle.value;
|
|
613
550
|
actions.push(...bundle.actions);
|
|
614
551
|
requirements.signatures.push(...bundle.requirements.signatures);
|
|
615
552
|
requirements.txs.push(...bundle.requirements.txs);
|
|
@@ -618,14 +555,6 @@ export function encodeBundle(operations, startData, supportsSignature = true) {
|
|
|
618
555
|
steps,
|
|
619
556
|
actions,
|
|
620
557
|
requirements,
|
|
621
|
-
tx: () => (
|
|
622
|
-
to: bundler,
|
|
623
|
-
value,
|
|
624
|
-
data: encodeFunctionData({
|
|
625
|
-
abi: baseBundlerAbi,
|
|
626
|
-
functionName: "multicall",
|
|
627
|
-
args: [actions.map(BundlerAction.encode)],
|
|
628
|
-
}),
|
|
629
|
-
}),
|
|
558
|
+
tx: () => BundlerAction.encodeBundle(chainId, actions),
|
|
630
559
|
};
|
|
631
560
|
}
|
package/lib/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SimulationResult } from "@morpho-org/simulation-sdk";
|
|
2
|
-
import type { InputBundlerOperation } from "./types/index.js";
|
|
2
|
+
import type { ActionType, InputBundlerOperation } from "./types/index.js";
|
|
3
3
|
export declare namespace BundlerErrors {
|
|
4
4
|
class Bundle extends Error {
|
|
5
5
|
readonly error: Error;
|
|
@@ -11,4 +11,7 @@ export declare namespace BundlerErrors {
|
|
|
11
11
|
class MissingSignature extends Error {
|
|
12
12
|
constructor();
|
|
13
13
|
}
|
|
14
|
+
class UnexpectedAction extends Error {
|
|
15
|
+
constructor(type: ActionType, chainId: number);
|
|
16
|
+
}
|
|
14
17
|
}
|
package/lib/errors.js
CHANGED
|
@@ -21,4 +21,10 @@ export var BundlerErrors;
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
BundlerErrors.MissingSignature = MissingSignature;
|
|
24
|
+
class UnexpectedAction extends Error {
|
|
25
|
+
constructor(type, chainId) {
|
|
26
|
+
super(`unexpected action "${type}" on chain "${chainId}"`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
BundlerErrors.UnexpectedAction = UnexpectedAction;
|
|
24
30
|
})(BundlerErrors || (BundlerErrors = {}));
|