@morpho-org/bundler-sdk-viem 3.0.0-next.16 → 3.0.0-next.18

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/actions.js CHANGED
@@ -5,6 +5,7 @@ import { getCurrent, 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 { ActionBundle, ActionBundleRequirements } from "./ActionBundle.js";
8
+ import { BundlerErrors } from "./errors.js";
8
9
  export const APPROVE_ONLY_ONCE_TOKENS = {
9
10
  [ChainId.EthMainnet]: [
10
11
  "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
@@ -65,7 +66,7 @@ const encodeErc20Approval = (token, sender, spender, amount, data) => {
65
66
  export const encodeOperation = (operation, dataBefore, supportsSignature = true, index = 0) => {
66
67
  const { chainId } = dataBefore;
67
68
  const deadline = Time.timestamp() + Time.s.from.h(24n);
68
- const { morpho, bundler3: { generalAdapter1 }, permit2, wNative, dai, wstEth, stEth, } = getChainAddresses(chainId);
69
+ const { morpho, bundler3: { bundler3, generalAdapter1 }, permit2, wNative, dai, wstEth, stEth, } = getChainAddresses(chainId);
69
70
  const actions = [];
70
71
  const requirements = new ActionBundleRequirements();
71
72
  let callbackBundle;
@@ -92,6 +93,9 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
92
93
  switch (operation.type) {
93
94
  case "Blue_SetAuthorization": {
94
95
  const { owner, isAuthorized, authorized } = operation.args;
96
+ // Never authorize bundler3 otherwise the signature can be used independently.
97
+ if (authorized === bundler3)
98
+ throw new BundlerErrors.UnexpectedSignature(authorized);
95
99
  if (supportsSignature) {
96
100
  const ownerData = dataBefore.getUser(owner);
97
101
  const authorization = {
@@ -158,6 +162,10 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
158
162
  if (address === NATIVE_ADDRESS)
159
163
  break;
160
164
  const { amount, spender, nonce } = operation.args;
165
+ // Never permit any other address than the GeneralAdapter1 otherwise
166
+ // the signature can be used independently.
167
+ if (spender !== generalAdapter1)
168
+ throw new BundlerErrors.UnexpectedSignature(spender);
161
169
  if (supportsSignature) {
162
170
  const action = address === dai
163
171
  ? {
@@ -168,7 +176,6 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
168
176
  deadline,
169
177
  true,
170
178
  null,
171
- spender,
172
179
  operation.skipRevert,
173
180
  ],
174
181
  }
@@ -180,7 +187,6 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
180
187
  amount,
181
188
  deadline,
182
189
  null,
183
- spender,
184
190
  operation.skipRevert,
185
191
  ],
186
192
  };
@@ -310,7 +316,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
310
316
  if (from === generalAdapter1) {
311
317
  actions.push({
312
318
  type: "erc20Transfer",
313
- args: [address, to, amount, undefined, operation.skipRevert],
319
+ args: [address, to, amount, generalAdapter1, operation.skipRevert],
314
320
  });
315
321
  break;
316
322
  }
@@ -342,14 +348,14 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
342
348
  case wNative: {
343
349
  actions.push({
344
350
  type: "wrapNative",
345
- args: [amount, undefined, operation.skipRevert],
351
+ args: [amount, generalAdapter1, operation.skipRevert],
346
352
  });
347
353
  break;
348
354
  }
349
355
  case wstEth: {
350
356
  actions.push({
351
357
  type: "wrapStEth",
352
- args: [amount, undefined, operation.skipRevert],
358
+ args: [amount, generalAdapter1, operation.skipRevert],
353
359
  });
354
360
  break;
355
361
  }
@@ -360,7 +366,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
360
366
  amount,
361
367
  MathLib.MAX_UINT_256,
362
368
  zeroAddress,
363
- undefined,
369
+ generalAdapter1,
364
370
  operation.skipRevert,
365
371
  ],
366
372
  });
@@ -390,14 +396,14 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
390
396
  case wNative: {
391
397
  actions.push({
392
398
  type: "unwrapNative",
393
- args: [amount, undefined, operation.skipRevert],
399
+ args: [amount, generalAdapter1, operation.skipRevert],
394
400
  });
395
401
  break;
396
402
  }
397
403
  case wstEth: {
398
404
  actions.push({
399
405
  type: "unwrapStEth",
400
- args: [amount, undefined, operation.skipRevert],
406
+ args: [amount, generalAdapter1, operation.skipRevert],
401
407
  });
402
408
  break;
403
409
  }
package/lib/errors.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { SimulationResult } from "@morpho-org/simulation-sdk";
2
+ import type { Address } from "viem";
2
3
  import type { ActionType, InputBundlerOperation } from "./types/index.js";
3
4
  export declare namespace BundlerErrors {
4
5
  class Bundle extends Error {
@@ -14,4 +15,7 @@ export declare namespace BundlerErrors {
14
15
  class UnexpectedAction extends Error {
15
16
  constructor(type: ActionType, chainId: number);
16
17
  }
18
+ class UnexpectedSignature extends Error {
19
+ constructor(spender: Address);
20
+ }
17
21
  }
package/lib/errors.js CHANGED
@@ -27,4 +27,10 @@ export var BundlerErrors;
27
27
  }
28
28
  }
29
29
  BundlerErrors.UnexpectedAction = UnexpectedAction;
30
+ class UnexpectedSignature extends Error {
31
+ constructor(spender) {
32
+ super(`unexpected signature consumer "${spender}"`);
33
+ }
34
+ }
35
+ BundlerErrors.UnexpectedSignature = UnexpectedSignature;
30
36
  })(BundlerErrors || (BundlerErrors = {}));
package/lib/operations.js CHANGED
@@ -216,29 +216,32 @@ export const populateSubBundle = (inputOperation, data, options = {}) => {
216
216
  ? MathLib.MAX_UINT_160
217
217
  : MathLib.wDivDown(newTotalBorrowAssets, supplyTargetUtilization) -
218
218
  newTotalSupplyAssets;
219
- let { withdrawals, data: simulationStatePostFriendlyReallocation } = data.getMarketPublicReallocations(market.id, publicAllocatorOptions);
220
- const marketPostFriendlyReallocation = simulationStatePostFriendlyReallocation.getMarket(market.id);
221
- if (marketPostFriendlyReallocation.totalBorrowAssets + borrowedAssets >
222
- marketPostFriendlyReallocation.totalSupplyAssets - withdrawnAssets) {
219
+ const { withdrawals, data: friendlyReallocationData } = data.getMarketPublicReallocations(market.id, publicAllocatorOptions);
220
+ const friendlyReallocationMarket = friendlyReallocationData.getMarket(market.id);
221
+ if (friendlyReallocationMarket.totalBorrowAssets + borrowedAssets >
222
+ friendlyReallocationMarket.totalSupplyAssets - withdrawnAssets) {
223
223
  // If the "friendly" reallocations are not enough, we fully withdraw from every market.
224
224
  requiredAssets = newTotalBorrowAssets - newTotalSupplyAssets;
225
- ({ withdrawals } = data.getMarketPublicReallocations(market.id, {
225
+ withdrawals.push(...friendlyReallocationData.getMarketPublicReallocations(market.id, {
226
226
  ...publicAllocatorOptions,
227
227
  defaultMaxWithdrawalUtilization: MathLib.WAD,
228
228
  maxWithdrawalUtilization: {},
229
- }));
229
+ }).withdrawals);
230
230
  }
231
231
  for (const { vault, ...withdrawal } of withdrawals) {
232
232
  const vaultReallocations = (reallocations[vault] ??= []);
233
- if (withdrawal.assets > requiredAssets) {
233
+ const vaultMarketReallocation = vaultReallocations.find((item) => item.id === withdrawal.id);
234
+ const reallocatedAssets = MathLib.min(withdrawal.assets, requiredAssets);
235
+ if (vaultMarketReallocation != null)
236
+ vaultMarketReallocation.assets += reallocatedAssets;
237
+ else
234
238
  vaultReallocations.push({
235
239
  ...withdrawal,
236
- assets: requiredAssets,
240
+ assets: reallocatedAssets,
237
241
  });
242
+ requiredAssets -= reallocatedAssets;
243
+ if (requiredAssets === 0n)
238
244
  break;
239
- }
240
- requiredAssets -= withdrawal.assets;
241
- vaultReallocations.push(withdrawal);
242
245
  }
243
246
  // TODO: we know there are no unwrap native in the middle
244
247
  // of the bundle so we are certain we need to add an input transfer.
@@ -32,13 +32,13 @@ export interface ActionArgs {
32
32
  asset: Address,
33
33
  recipient: Address,
34
34
  amount: bigint,
35
- adapter?: Address,
35
+ adapter: Address,
36
36
  skipRevert?: boolean
37
37
  ];
38
38
  erc20TransferFrom: [
39
39
  asset: Address,
40
40
  amount: bigint,
41
- recipient?: Address,
41
+ recipient: Address,
42
42
  skipRevert?: boolean
43
43
  ];
44
44
  erc20WrapperDepositFor: [
@@ -59,7 +59,6 @@ export interface ActionArgs {
59
59
  amount: bigint,
60
60
  deadline: bigint,
61
61
  signature: Hex | null,
62
- spender?: Address,
63
62
  skipRevert?: boolean
64
63
  ];
65
64
  permitDai: [
@@ -68,7 +67,6 @@ export interface ActionArgs {
68
67
  expiry: bigint,
69
68
  allowed: boolean,
70
69
  signature: Hex | null,
71
- spender?: Address,
72
70
  skipRevert?: boolean
73
71
  ];
74
72
  approve2: [
@@ -80,7 +78,7 @@ export interface ActionArgs {
80
78
  transferFrom2: [
81
79
  asset: Address,
82
80
  amount: bigint,
83
- recipient?: Address,
81
+ recipient: Address,
84
82
  skipRevert?: boolean
85
83
  ];
86
84
  erc4626Mint: [
@@ -114,13 +112,7 @@ export interface ActionArgs {
114
112
  skipRevert?: boolean
115
113
  ];
116
114
  morphoSetAuthorizationWithSig: [
117
- authorization: {
118
- authorizer: Address;
119
- authorized: Address;
120
- isAuthorized: boolean;
121
- nonce: bigint;
122
- deadline: bigint;
123
- },
115
+ authorization: Authorization,
124
116
  signature: Hex | null,
125
117
  skipRevert?: boolean
126
118
  ];
@@ -186,17 +178,17 @@ export interface ActionArgs {
186
178
  proof: Hex[],
187
179
  skipRevert?: boolean
188
180
  ];
189
- wrapNative: [amount: bigint, recipient?: Address, skipRevert?: boolean];
190
- unwrapNative: [amount: bigint, recipient?: Address, skipRevert?: boolean];
181
+ wrapNative: [amount: bigint, recipient: Address, skipRevert?: boolean];
182
+ unwrapNative: [amount: bigint, recipient: Address, skipRevert?: boolean];
191
183
  stakeEth: [
192
184
  amount: bigint,
193
185
  minShares: bigint,
194
186
  referral: Address,
195
- recipient?: Address,
187
+ recipient: Address,
196
188
  skipRevert?: boolean
197
189
  ];
198
- wrapStEth: [amount: bigint, recipient?: Address, skipRevert?: boolean];
199
- unwrapStEth: [amount: bigint, recipient?: Address, skipRevert?: boolean];
190
+ wrapStEth: [amount: bigint, recipient: Address, skipRevert?: boolean];
191
+ unwrapStEth: [amount: bigint, recipient: Address, skipRevert?: boolean];
200
192
  aaveV2Repay: [
201
193
  asset: Address,
202
194
  amount: bigint,
@@ -207,7 +199,7 @@ export interface ActionArgs {
207
199
  aaveV2Withdraw: [
208
200
  asset: Address,
209
201
  amount: bigint,
210
- recipient?: Address,
202
+ recipient: Address,
211
203
  skipRevert?: boolean
212
204
  ];
213
205
  aaveV3Repay: [
@@ -220,7 +212,7 @@ export interface ActionArgs {
220
212
  aaveV3Withdraw: [
221
213
  asset: Address,
222
214
  amount: bigint,
223
- recipient?: Address,
215
+ recipient: Address,
224
216
  skipRevert?: boolean
225
217
  ];
226
218
  aaveV3OptimizerRepay: [
@@ -233,13 +225,13 @@ export interface ActionArgs {
233
225
  underlying: Address,
234
226
  amount: bigint,
235
227
  maxIterations: bigint,
236
- recipient?: Address,
228
+ recipient: Address,
237
229
  skipRevert?: boolean
238
230
  ];
239
231
  aaveV3OptimizerWithdrawCollateral: [
240
232
  underlying: Address,
241
233
  amount: bigint,
242
- recipient?: Address,
234
+ recipient: Address,
243
235
  skipRevert?: boolean
244
236
  ];
245
237
  aaveV3OptimizerApproveManagerWithSig: [
@@ -249,7 +241,6 @@ export interface ActionArgs {
249
241
  nonce: bigint,
250
242
  deadline: bigint,
251
243
  signature: Hex | null,
252
- manager?: Address,
253
244
  skipRevert?: boolean
254
245
  ];
255
246
  compoundV2Repay: [
@@ -263,7 +254,7 @@ export interface ActionArgs {
263
254
  cToken: Address,
264
255
  amount: bigint,
265
256
  isEth: boolean,
266
- recipient?: Address,
257
+ recipient: Address,
267
258
  skipRevert?: boolean
268
259
  ];
269
260
  compoundV3Repay: [
@@ -276,7 +267,7 @@ export interface ActionArgs {
276
267
  instance: Address,
277
268
  asset: Address,
278
269
  amount: bigint,
279
- recipient?: Address,
270
+ recipient: Address,
280
271
  skipRevert?: boolean
281
272
  ];
282
273
  compoundV3AllowBySig: [
@@ -286,7 +277,6 @@ export interface ActionArgs {
286
277
  nonce: bigint,
287
278
  expiry: bigint,
288
279
  signature: Hex | null,
289
- manager?: Address,
290
280
  skipRevert?: boolean
291
281
  ];
292
282
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morpho-org/bundler-sdk-viem",
3
3
  "description": "Viem-based extension of `@morpho-org/simulation-sdk` that exports utilities to transform simple interactions on Morpho (such as `Blue_Borrow`) and Morpho Vaults (such as `MetaMorpho_Deposit`) into the required bundles (with ERC20 approvals, transfers, etc) to submit to the bundler onchain.",
4
- "version": "3.0.0-next.16",
4
+ "version": "3.0.0-next.18",
5
5
  "author": "Morpho Association <contact@morpho.org>",
6
6
  "contributors": [
7
7
  "Rubilmax <rmilon@gmail.com>"
@@ -20,8 +20,8 @@
20
20
  ],
21
21
  "peerDependencies": {
22
22
  "viem": "^2.0.0",
23
- "@morpho-org/blue-sdk-viem": "^2.2.2",
24
23
  "@morpho-org/blue-sdk": "^2.3.2",
24
+ "@morpho-org/blue-sdk-viem": "^2.2.2",
25
25
  "@morpho-org/morpho-ts": "^2.2.0",
26
26
  "@morpho-org/simulation-sdk": "^2.1.4"
27
27
  },
@@ -38,11 +38,11 @@
38
38
  "@morpho-org/blue-sdk": "^2.3.2",
39
39
  "@morpho-org/morpho-test": "^2.2.1",
40
40
  "@morpho-org/morpho-ts": "^2.2.0",
41
- "@morpho-org/simulation-sdk": "^2.1.4",
42
41
  "@morpho-org/blue-sdk-viem": "^2.2.2",
43
- "@morpho-org/test": "^2.1.1",
42
+ "@morpho-org/simulation-sdk": "^2.1.4",
44
43
  "@morpho-org/simulation-sdk-wagmi": "^2.0.5",
45
- "@morpho-org/test-wagmi": "^2.0.4"
44
+ "@morpho-org/test-wagmi": "^2.0.4",
45
+ "@morpho-org/test": "^2.1.2-next.0"
46
46
  },
47
47
  "scripts": {
48
48
  "prepublish": "$npm_execpath build",