@panoptic-eng/sdk 1.0.20 → 1.0.22

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.
Files changed (36) hide show
  1. package/dist/cow/index.js +3 -3
  2. package/dist/{cow-Cqw3sako.js → cow-C_SGXoWr.js} +2 -2
  3. package/dist/{cow-Cqw3sako.js.map → cow-C_SGXoWr.js.map} +1 -1
  4. package/dist/index.d.ts +696 -5907
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1393 -579
  7. package/dist/index.js.map +1 -1
  8. package/dist/irm-C7OUVANR.d.ts +5641 -0
  9. package/dist/irm-C7OUVANR.d.ts.map +1 -0
  10. package/dist/{irm-DF4NwYIY.js → irm-DNK3N7qk.js} +301 -3
  11. package/dist/irm-DNK3N7qk.js.map +1 -0
  12. package/dist/panoptic/v2/index.d.ts +12 -4
  13. package/dist/panoptic/v2/index.d.ts.map +1 -1
  14. package/dist/panoptic/v2/index.js +25 -10
  15. package/dist/panoptic/v2/index.js.map +1 -1
  16. package/dist/{position-zqvENVuf.js → position-BK4a-Yyu.js} +2 -2
  17. package/dist/{position-zqvENVuf.js.map → position-BK4a-Yyu.js.map} +1 -1
  18. package/dist/{router-d09dxd-F.js → router-BZvOeloX.js} +90 -40
  19. package/dist/router-BZvOeloX.js.map +1 -0
  20. package/dist/test/index.d.ts +2 -2
  21. package/dist/test/index.d.ts.map +1 -1
  22. package/dist/uniswap/index.d.ts +118 -1
  23. package/dist/uniswap/index.d.ts.map +1 -1
  24. package/dist/uniswap/index.js +228 -4
  25. package/dist/uniswap/index.js.map +1 -0
  26. package/dist/{writes-CRjVFjMt.js → writes-DymnVbiE.js} +2 -2
  27. package/dist/{writes-CRjVFjMt.js.map → writes-DymnVbiE.js.map} +1 -1
  28. package/dist/zodiac/index.d.ts +444 -0
  29. package/dist/zodiac/index.d.ts.map +1 -0
  30. package/dist/zodiac/index.js +949 -0
  31. package/dist/zodiac/index.js.map +1 -0
  32. package/package.json +6 -1
  33. package/dist/irm-DF4NwYIY.js.map +0 -1
  34. package/dist/irm-zWjtffWA.d.ts +0 -85
  35. package/dist/irm-zWjtffWA.d.ts.map +0 -1
  36. package/dist/router-d09dxd-F.js.map +0 -1
@@ -0,0 +1,949 @@
1
+ import { keccak256, toBytes, toFunctionSelector } from "viem";
2
+
3
+ //#region src/zodiac/rolesAbi.ts
4
+ /** Minimal Zodiac Roles v2 modifier ABI used by the scoping/apply flows. */
5
+ const rolesV2Abi = [
6
+ {
7
+ type: "function",
8
+ name: "assignRoles",
9
+ stateMutability: "nonpayable",
10
+ inputs: [
11
+ {
12
+ name: "module",
13
+ type: "address"
14
+ },
15
+ {
16
+ name: "roleKeys",
17
+ type: "bytes32[]"
18
+ },
19
+ {
20
+ name: "memberOf",
21
+ type: "bool[]"
22
+ }
23
+ ],
24
+ outputs: []
25
+ },
26
+ {
27
+ type: "function",
28
+ name: "scopeTarget",
29
+ stateMutability: "nonpayable",
30
+ inputs: [{
31
+ name: "roleKey",
32
+ type: "bytes32"
33
+ }, {
34
+ name: "targetAddress",
35
+ type: "address"
36
+ }],
37
+ outputs: []
38
+ },
39
+ {
40
+ type: "function",
41
+ name: "scopeFunction",
42
+ stateMutability: "nonpayable",
43
+ inputs: [
44
+ {
45
+ name: "roleKey",
46
+ type: "bytes32"
47
+ },
48
+ {
49
+ name: "targetAddress",
50
+ type: "address"
51
+ },
52
+ {
53
+ name: "selector",
54
+ type: "bytes4"
55
+ },
56
+ {
57
+ name: "conditions",
58
+ type: "tuple[]",
59
+ components: [
60
+ {
61
+ name: "parent",
62
+ type: "uint8"
63
+ },
64
+ {
65
+ name: "paramType",
66
+ type: "uint8"
67
+ },
68
+ {
69
+ name: "operator",
70
+ type: "uint8"
71
+ },
72
+ {
73
+ name: "compValue",
74
+ type: "bytes"
75
+ }
76
+ ]
77
+ },
78
+ {
79
+ name: "options",
80
+ type: "uint8"
81
+ }
82
+ ],
83
+ outputs: []
84
+ },
85
+ {
86
+ type: "function",
87
+ name: "allowFunction",
88
+ stateMutability: "nonpayable",
89
+ inputs: [
90
+ {
91
+ name: "roleKey",
92
+ type: "bytes32"
93
+ },
94
+ {
95
+ name: "targetAddress",
96
+ type: "address"
97
+ },
98
+ {
99
+ name: "selector",
100
+ type: "bytes4"
101
+ },
102
+ {
103
+ name: "options",
104
+ type: "uint8"
105
+ }
106
+ ],
107
+ outputs: []
108
+ },
109
+ {
110
+ type: "function",
111
+ name: "setTransactionUnwrapper",
112
+ stateMutability: "nonpayable",
113
+ inputs: [
114
+ {
115
+ name: "to",
116
+ type: "address"
117
+ },
118
+ {
119
+ name: "selector",
120
+ type: "bytes4"
121
+ },
122
+ {
123
+ name: "adapter",
124
+ type: "address"
125
+ }
126
+ ],
127
+ outputs: []
128
+ }
129
+ ];
130
+
131
+ //#endregion
132
+ //#region src/zodiac/applySteps.ts
133
+ /**
134
+ * Apply scope steps to a Roles v2 modifier sequentially, aborting on the
135
+ * first revert so a partially-applied role is never silently left behind.
136
+ * The wallet must be the modifier's owner.
137
+ */
138
+ async function applyScopeSteps(params) {
139
+ const { publicClient, walletClient, rolesModifier, steps, log = console.log } = params;
140
+ for (const step of steps) {
141
+ log(`→ ${step.name}`);
142
+ const hash = await walletClient.writeContract({
143
+ address: rolesModifier,
144
+ abi: rolesV2Abi,
145
+ functionName: step.functionName,
146
+ args: step.args,
147
+ ...params.fees ?? {}
148
+ });
149
+ const receipt = await publicClient.waitForTransactionReceipt({
150
+ hash,
151
+ ...params.timeoutMs ? { timeout: params.timeoutMs } : {}
152
+ });
153
+ log(` ${receipt.status} ${hash}`);
154
+ if (receipt.status !== "success") throw new Error(`step "${step.name}" reverted (tx ${hash}); aborting before later steps`);
155
+ }
156
+ }
157
+
158
+ //#endregion
159
+ //#region src/zodiac/conditions.ts
160
+ /** True for a 0x-prefixed, 20-byte (40 hex char) address. */
161
+ function isHexAddress(v) {
162
+ return /^0x[0-9a-fA-F]{40}$/.test(v);
163
+ }
164
+ /** 32-byte left-padded address as an EqualTo Static compValue. */
165
+ function addressEqualCompValue(addr) {
166
+ if (!isHexAddress(addr)) throw new Error(`addressEqualCompValue: expected a 20-byte hex address, got "${addr}"`);
167
+ return `0x${addr.slice(2).toLowerCase().padStart(64, "0")}`;
168
+ }
169
+ /**
170
+ * Operator.Custom compValue: adapter address in the leading 20 bytes, the
171
+ * trailing 12 bytes are passed to the adapter verbatim as `extra`.
172
+ */
173
+ function customCompValue(adapter, extra = "0x") {
174
+ if (!isHexAddress(adapter)) throw new Error(`customCompValue: adapter must be a 20-byte hex address, got "${adapter}"`);
175
+ if (!/^0x([0-9a-fA-F]{2})*$/.test(extra)) throw new Error(`customCompValue: extra must be 0x-prefixed, even-length hex, got "${extra}"`);
176
+ if (extra.length - 2 > 24) throw new Error("customCompValue: extra must be at most 12 bytes");
177
+ const extraHex = extra.slice(2).padEnd(24, "0");
178
+ return `0x${adapter.slice(2).toLowerCase()}${extraHex}`;
179
+ }
180
+ /**
181
+ * Encode a uint96 mint-size cap as the `bytes12 extra` of a pair-condition
182
+ * compValue (0n = uncapped). The adapters read it as `uint96(extra)`, i.e.
183
+ * big-endian right-aligned in the 12 bytes.
184
+ */
185
+ function sizeCapExtra(cap) {
186
+ if (cap < 0n || cap >= 1n << 96n) throw new Error("size cap must fit in uint96");
187
+ return `0x${cap.toString(16).padStart(24, "0")}`;
188
+ }
189
+
190
+ //#endregion
191
+ //#region src/zodiac/constants.ts
192
+ /**
193
+ * Zodiac Roles Modifier v2 enum ordinals.
194
+ *
195
+ * Verified against gnosisguild/zodiac-modifier-roles `contracts/Types.sol`
196
+ * (commit c343958ab7317b31d8c4aec790606d950ea21eed) and the deployed v2.1
197
+ * mastercopy 0x9646fDAD06d3e24444381f44362a3B0eB343D337. Keep in sync with the
198
+ * modifier version the Safe actually runs.
199
+ */
200
+ const ParameterType = {
201
+ None: 0,
202
+ Static: 1,
203
+ Dynamic: 2,
204
+ Tuple: 3,
205
+ Array: 4,
206
+ Calldata: 5,
207
+ AbiEncoded: 6
208
+ };
209
+ const Operator = {
210
+ Pass: 0,
211
+ And: 1,
212
+ Or: 2,
213
+ Nor: 3,
214
+ Matches: 5,
215
+ ArraySome: 6,
216
+ ArrayEvery: 7,
217
+ ArraySubset: 8,
218
+ EqualToAvatar: 15,
219
+ EqualTo: 16,
220
+ GreaterThan: 17,
221
+ LessThan: 18,
222
+ SignedIntGreaterThan: 19,
223
+ SignedIntLessThan: 20,
224
+ Bitmask: 21,
225
+ Custom: 22,
226
+ WithinAllowance: 28,
227
+ EtherWithinAllowance: 29,
228
+ CallWithinAllowance: 30
229
+ };
230
+ /**
231
+ * Canonical adapter addresses — deterministic CREATE2 (factory
232
+ * 0x4e59b44847b379578588920cA78FbF26c0B4956C, salt
233
+ * keccak256("panoptic.zodiac-modules.v1")), so they depend only on the
234
+ * bytecode: same on every chain, deployer-independent, verifiable with
235
+ * `cast code` against a local `forge build`. The adapters are stateless and
236
+ * immutable (no owner/storage/upgradability). Recompute via
237
+ * `forge script scripts/DeployAdapters.s.sol` after any source change.
238
+ */
239
+ const CANONICAL_ADAPTERS = {
240
+ RollerCondition: "0x7b2402F7Ff7fFe0970D383dE1C6AF8892B87523a",
241
+ SizeAdjusterCondition: "0x72494B2A0C5a69Dd0154386c2F4Af0b38a24C400"
242
+ };
243
+ const ExecutionOptions = {
244
+ None: 0,
245
+ Send: 1,
246
+ DelegateCall: 2,
247
+ Both: 3
248
+ };
249
+
250
+ //#endregion
251
+ //#region src/zodiac/roles/dispatchCustomRole.ts
252
+ /** PanopticPool.dispatch — TokenId is a uint256 value type. */
253
+ const DISPATCH_SELECTOR = toFunctionSelector("dispatch(uint256[],uint256[],uint128[],int24[3][],bool,uint256)");
254
+ /** Deterministic per-role keys; override via env/config if a Safe needs several instances. */
255
+ function roleKey(name) {
256
+ return keccak256(toBytes(`panoptic.role.${name}.v1`));
257
+ }
258
+ /**
259
+ * ConditionFlat tree for a dispatch-scoped role whose whole authorization
260
+ * logic lives in an on-chain `ICustomCondition` adapter (Operator.Custom).
261
+ *
262
+ * The Custom node is attached to arg0 (`positionIdList`): Roles hands the
263
+ * adapter the FULL calldata regardless of attachment point, and the adapter
264
+ * decodes `positionIdList`/`positionSizes` itself. The remaining nodes are the
265
+ * structural template `Integrity.sol` requires (Calldata and Array nodes must
266
+ * describe their children; see buildLoanOnlyDispatchConditions for the shape).
267
+ */
268
+ function buildDispatchCustomConditions(adapter, extra = "0x") {
269
+ const compValue = customCompValue(adapter, extra);
270
+ return [
271
+ {
272
+ parent: 0,
273
+ paramType: ParameterType.Calldata,
274
+ operator: Operator.Matches,
275
+ compValue: "0x"
276
+ },
277
+ {
278
+ parent: 0,
279
+ paramType: ParameterType.Array,
280
+ operator: Operator.Custom,
281
+ compValue
282
+ },
283
+ {
284
+ parent: 0,
285
+ paramType: ParameterType.Array,
286
+ operator: Operator.Pass,
287
+ compValue: "0x"
288
+ },
289
+ {
290
+ parent: 0,
291
+ paramType: ParameterType.Array,
292
+ operator: Operator.Pass,
293
+ compValue: "0x"
294
+ },
295
+ {
296
+ parent: 0,
297
+ paramType: ParameterType.Array,
298
+ operator: Operator.Pass,
299
+ compValue: "0x"
300
+ },
301
+ {
302
+ parent: 0,
303
+ paramType: ParameterType.Static,
304
+ operator: Operator.Pass,
305
+ compValue: "0x"
306
+ },
307
+ {
308
+ parent: 0,
309
+ paramType: ParameterType.Static,
310
+ operator: Operator.Pass,
311
+ compValue: "0x"
312
+ },
313
+ {
314
+ parent: 1,
315
+ paramType: ParameterType.Static,
316
+ operator: Operator.Pass,
317
+ compValue: "0x"
318
+ },
319
+ {
320
+ parent: 2,
321
+ paramType: ParameterType.Static,
322
+ operator: Operator.Pass,
323
+ compValue: "0x"
324
+ },
325
+ {
326
+ parent: 3,
327
+ paramType: ParameterType.Static,
328
+ operator: Operator.Pass,
329
+ compValue: "0x"
330
+ },
331
+ {
332
+ parent: 4,
333
+ paramType: ParameterType.Tuple,
334
+ operator: Operator.Pass,
335
+ compValue: "0x"
336
+ },
337
+ {
338
+ parent: 10,
339
+ paramType: ParameterType.Static,
340
+ operator: Operator.Pass,
341
+ compValue: "0x"
342
+ },
343
+ {
344
+ parent: 10,
345
+ paramType: ParameterType.Static,
346
+ operator: Operator.Pass,
347
+ compValue: "0x"
348
+ },
349
+ {
350
+ parent: 10,
351
+ paramType: ParameterType.Static,
352
+ operator: Operator.Pass,
353
+ compValue: "0x"
354
+ }
355
+ ];
356
+ }
357
+ /** assignRoles → scopeTarget → scopeFunction steps for an adapter-gated dispatch role. */
358
+ function buildDispatchCustomRoleSteps(params) {
359
+ const { roleName, member, pool, adapter, extra } = params;
360
+ return [
361
+ {
362
+ name: `assignRoles(${roleName} member)`,
363
+ functionName: "assignRoles",
364
+ args: [
365
+ member,
366
+ [params.roleKey],
367
+ [true]
368
+ ]
369
+ },
370
+ {
371
+ name: "scopeTarget(pool)",
372
+ functionName: "scopeTarget",
373
+ args: [params.roleKey, pool]
374
+ },
375
+ {
376
+ name: `scopeFunction(dispatch, ${roleName} custom adapter)`,
377
+ functionName: "scopeFunction",
378
+ args: [
379
+ params.roleKey,
380
+ pool,
381
+ DISPATCH_SELECTOR,
382
+ buildDispatchCustomConditions(adapter, extra),
383
+ ExecutionOptions.None
384
+ ]
385
+ }
386
+ ];
387
+ }
388
+
389
+ //#endregion
390
+ //#region src/zodiac/roles/deleverager.ts
391
+ /**
392
+ * Deleverager role: burn the Safe's existing positions only — never mint.
393
+ *
394
+ * Enforced with plain static conditions, no adapter and no state oracle:
395
+ * every `positionSizes` entry must be 0. A size-0 entry either burns a held
396
+ * position or reverts the whole dispatch — a size-0 mint is impossible
397
+ * (option legs trip `ChunkHasZeroLiquidity` in the SFPM; pure-loan tokenIds
398
+ * die in the end-of-dispatch solvency pass / positions-hash validation).
399
+ *
400
+ * Trade-off vs an oracle-based check: the key cannot settle premium (settle
401
+ * requires `sizes[i] == storedSize`, unknowable pre-execution). Strictly a
402
+ * risk-reduction key: safe for a watchdog keeper or dead-man's-switch.
403
+ */
404
+ const DELEVERAGER_ROLE_KEY = roleKey("deleverager");
405
+ const ZERO_WORD = `0x${"0".repeat(64)}`;
406
+ function buildDeleveragerDispatchConditions() {
407
+ return [
408
+ {
409
+ parent: 0,
410
+ paramType: ParameterType.Calldata,
411
+ operator: Operator.Matches,
412
+ compValue: "0x"
413
+ },
414
+ {
415
+ parent: 0,
416
+ paramType: ParameterType.Array,
417
+ operator: Operator.Pass,
418
+ compValue: "0x"
419
+ },
420
+ {
421
+ parent: 0,
422
+ paramType: ParameterType.Array,
423
+ operator: Operator.Pass,
424
+ compValue: "0x"
425
+ },
426
+ {
427
+ parent: 0,
428
+ paramType: ParameterType.Array,
429
+ operator: Operator.ArrayEvery,
430
+ compValue: "0x"
431
+ },
432
+ {
433
+ parent: 0,
434
+ paramType: ParameterType.Array,
435
+ operator: Operator.Pass,
436
+ compValue: "0x"
437
+ },
438
+ {
439
+ parent: 0,
440
+ paramType: ParameterType.Static,
441
+ operator: Operator.Pass,
442
+ compValue: "0x"
443
+ },
444
+ {
445
+ parent: 0,
446
+ paramType: ParameterType.Static,
447
+ operator: Operator.Pass,
448
+ compValue: "0x"
449
+ },
450
+ {
451
+ parent: 1,
452
+ paramType: ParameterType.Static,
453
+ operator: Operator.Pass,
454
+ compValue: "0x"
455
+ },
456
+ {
457
+ parent: 2,
458
+ paramType: ParameterType.Static,
459
+ operator: Operator.Pass,
460
+ compValue: "0x"
461
+ },
462
+ {
463
+ parent: 3,
464
+ paramType: ParameterType.Static,
465
+ operator: Operator.EqualTo,
466
+ compValue: ZERO_WORD
467
+ },
468
+ {
469
+ parent: 4,
470
+ paramType: ParameterType.Tuple,
471
+ operator: Operator.Pass,
472
+ compValue: "0x"
473
+ },
474
+ {
475
+ parent: 10,
476
+ paramType: ParameterType.Static,
477
+ operator: Operator.Pass,
478
+ compValue: "0x"
479
+ },
480
+ {
481
+ parent: 10,
482
+ paramType: ParameterType.Static,
483
+ operator: Operator.Pass,
484
+ compValue: "0x"
485
+ },
486
+ {
487
+ parent: 10,
488
+ paramType: ParameterType.Static,
489
+ operator: Operator.Pass,
490
+ compValue: "0x"
491
+ }
492
+ ];
493
+ }
494
+ function buildDeleveragerRoleSteps(params) {
495
+ const key = params.roleKey ?? DELEVERAGER_ROLE_KEY;
496
+ return [
497
+ {
498
+ name: "assignRoles(deleverager member)",
499
+ functionName: "assignRoles",
500
+ args: [
501
+ params.member,
502
+ [key],
503
+ [true]
504
+ ]
505
+ },
506
+ {
507
+ name: "scopeTarget(pool)",
508
+ functionName: "scopeTarget",
509
+ args: [key, params.pool]
510
+ },
511
+ {
512
+ name: "scopeFunction(dispatch, burn-only: all sizes == 0)",
513
+ functionName: "scopeFunction",
514
+ args: [
515
+ key,
516
+ params.pool,
517
+ DISPATCH_SELECTOR,
518
+ buildDeleveragerDispatchConditions(),
519
+ ExecutionOptions.None
520
+ ]
521
+ }
522
+ ];
523
+ }
524
+
525
+ //#endregion
526
+ //#region src/zodiac/tokenIdMask.ts
527
+ /**
528
+ * Bit-field masks over the Panoptic v2 tokenId layout, mirroring
529
+ * `contracts/lib/TokenIdMasks.sol` (kept in lockstep by golden unit tests).
530
+ *
531
+ * Layout (packages/panoptic-v2-core/contracts/types/TokenId.sol):
532
+ * - bits [0, 64) poolId
533
+ * - each leg is 48 bits, starting at 64 + legIndex*48, packing
534
+ * asset(+0,1b) | optionRatio(+1,7b) | isLong(+8) | tokenType(+9)
535
+ * | riskPartner(+10,2b) | strike(+12,24b) | width(+36,12b)
536
+ */
537
+ const POOL_ID_SIZE = 64n;
538
+ const LEG_SIZE = 48n;
539
+ const MAX_LEGS = 4n;
540
+ /** Mask with 1-bits over a `bits`-wide field at `fieldOffset` in every leg. */
541
+ function legFieldMask(fieldOffset, bits) {
542
+ const field = (1n << bits) - 1n;
543
+ let mask = 0n;
544
+ for (let leg = 0n; leg < MAX_LEGS; leg++) mask |= field << POOL_ID_SIZE + leg * LEG_SIZE + fieldOffset;
545
+ return mask;
546
+ }
547
+ /** Mask with 1-bits over every leg's 12-bit width field. */
548
+ function loanWidthFieldsMask() {
549
+ return legFieldMask(36n, 12n);
550
+ }
551
+ /** Mask with 1-bits over every leg's 24-bit strike field. */
552
+ function strikeFieldsMask() {
553
+ return legFieldMask(12n, 24n);
554
+ }
555
+ /** Mask with 1-bits over every leg's 7-bit optionRatio field. */
556
+ function optionRatioFieldsMask() {
557
+ return legFieldMask(1n, 7n);
558
+ }
559
+ /** True iff every leg of the tokenId has width == 0 (a pure loan/credit). */
560
+ function isPureLoanTokenId(tokenId) {
561
+ return (tokenId & loanWidthFieldsMask()) === 0n;
562
+ }
563
+ /** The 32-byte mask + expected value for a Zodiac Roles v2 Bitmask condition. */
564
+ function loanBitmaskCondition() {
565
+ const mask = loanWidthFieldsMask();
566
+ const toBytes32 = (v) => `0x${v.toString(16).padStart(64, "0")}`;
567
+ return {
568
+ mask: toBytes32(mask),
569
+ expected: toBytes32(0n)
570
+ };
571
+ }
572
+
573
+ //#endregion
574
+ //#region src/zodiac/roles/loanHedger.ts
575
+ /**
576
+ * Loan-only hedger role scope (migrated from apps/hedger-bot scripts/lib).
577
+ *
578
+ * ⚠️ VALIDATE ON A FORK BEFORE MAINNET. The ConditionFlat encoding below is
579
+ * security-critical. Dry-run `scopeFunction` on an anvil/Tenderly fork and
580
+ * assert that the role CAN mint/burn a pure width=0 loan via dispatch and
581
+ * CANNOT dispatch a tokenId with any width>0 leg.
582
+ *
583
+ * The scope constrains PanopticPool.dispatch(positionIdList, finalPositionIdList,
584
+ * positionSizes, tickAndSpreadLimits, usePremiaAsCollateral, builderCode) so that
585
+ * EVERY element of `positionIdList` (arg 0 — the tokenIds actually minted/burned)
586
+ * is a pure loan: `tokenId & widthFieldsMask == 0`. All other args pass freely;
587
+ * `finalPositionIdList` is intentionally NOT constrained (it legitimately contains
588
+ * the user's option positions that remain open).
589
+ */
590
+ /**
591
+ * Bitmask compValue layout (Roles v2 `PermissionChecker._bitmask`): a 32-byte
592
+ * word packing `uint16 shift | bytes15 mask | bytes15 expected`, where `shift`
593
+ * is a BYTE offset from the start (left / most-significant end) of the value
594
+ * and the 15-byte mask is applied LEFT-aligned to `bytes32(value[shift:])`.
595
+ *
596
+ * The four 12-bit width fields span tokenId bits 100–255 (leg 3's width sits in
597
+ * the top two bytes), which is wider than one 15-byte window. So the loan
598
+ * constraint is expressed as TWO windows AND-ed together:
599
+ * - shift 0: tokenId bytes 0..14 (bits 136–255) — covers legs 1, 2, 3
600
+ * - shift 17: tokenId bytes 17..31 (bits 0–119) — covers leg 0
601
+ * Bytes 15–16 (bits 120–135) contain no width bits.
602
+ */
603
+ const LOAN_BITMASK_WINDOW_SHIFTS = [0, 17];
604
+ function loanBitmaskCompValueAt(shiftBytes) {
605
+ const { mask } = loanBitmaskCondition();
606
+ const maskBytes = mask.slice(2);
607
+ const window = maskBytes.slice(shiftBytes * 2, shiftBytes * 2 + 30).padEnd(30, "0");
608
+ const shift = shiftBytes.toString(16).padStart(4, "0");
609
+ return `0x${shift}${window}${"0".repeat(30)}`;
610
+ }
611
+ /**
612
+ * Build the ConditionFlat[] tree scoping dispatch to loan-only positionIdList.
613
+ *
614
+ * Roles v2 `Integrity.sol` requirements honored here:
615
+ * - BFS order: parent indices must be non-decreasing (NotBFS).
616
+ * - Every Array-typed node needs >=1 child describing the element type
617
+ * (UnsuitableChildCount); ArrayEvery needs exactly 1.
618
+ * - And nodes use ParameterType.None and an empty compValue.
619
+ */
620
+ function buildLoanOnlyDispatchConditions() {
621
+ return [
622
+ {
623
+ parent: 0,
624
+ paramType: ParameterType.Calldata,
625
+ operator: Operator.Matches,
626
+ compValue: "0x"
627
+ },
628
+ {
629
+ parent: 0,
630
+ paramType: ParameterType.Array,
631
+ operator: Operator.ArrayEvery,
632
+ compValue: "0x"
633
+ },
634
+ {
635
+ parent: 0,
636
+ paramType: ParameterType.Array,
637
+ operator: Operator.Pass,
638
+ compValue: "0x"
639
+ },
640
+ {
641
+ parent: 0,
642
+ paramType: ParameterType.Array,
643
+ operator: Operator.Pass,
644
+ compValue: "0x"
645
+ },
646
+ {
647
+ parent: 0,
648
+ paramType: ParameterType.Array,
649
+ operator: Operator.Pass,
650
+ compValue: "0x"
651
+ },
652
+ {
653
+ parent: 0,
654
+ paramType: ParameterType.Static,
655
+ operator: Operator.Pass,
656
+ compValue: "0x"
657
+ },
658
+ {
659
+ parent: 0,
660
+ paramType: ParameterType.Static,
661
+ operator: Operator.Pass,
662
+ compValue: "0x"
663
+ },
664
+ {
665
+ parent: 1,
666
+ paramType: ParameterType.None,
667
+ operator: Operator.And,
668
+ compValue: "0x"
669
+ },
670
+ {
671
+ parent: 2,
672
+ paramType: ParameterType.Static,
673
+ operator: Operator.Pass,
674
+ compValue: "0x"
675
+ },
676
+ {
677
+ parent: 3,
678
+ paramType: ParameterType.Static,
679
+ operator: Operator.Pass,
680
+ compValue: "0x"
681
+ },
682
+ {
683
+ parent: 4,
684
+ paramType: ParameterType.Tuple,
685
+ operator: Operator.Pass,
686
+ compValue: "0x"
687
+ },
688
+ {
689
+ parent: 7,
690
+ paramType: ParameterType.Static,
691
+ operator: Operator.Bitmask,
692
+ compValue: loanBitmaskCompValueAt(LOAN_BITMASK_WINDOW_SHIFTS[0])
693
+ },
694
+ {
695
+ parent: 7,
696
+ paramType: ParameterType.Static,
697
+ operator: Operator.Bitmask,
698
+ compValue: loanBitmaskCompValueAt(LOAN_BITMASK_WINDOW_SHIFTS[1])
699
+ },
700
+ {
701
+ parent: 10,
702
+ paramType: ParameterType.Static,
703
+ operator: Operator.Pass,
704
+ compValue: "0x"
705
+ },
706
+ {
707
+ parent: 10,
708
+ paramType: ParameterType.Static,
709
+ operator: Operator.Pass,
710
+ compValue: "0x"
711
+ },
712
+ {
713
+ parent: 10,
714
+ paramType: ParameterType.Static,
715
+ operator: Operator.Pass,
716
+ compValue: "0x"
717
+ }
718
+ ];
719
+ }
720
+ /** ERC4626 CollateralTracker withdraw(uint256 assets, address receiver, address owner). */
721
+ const WITHDRAW_SELECTOR = "0xb460af94";
722
+ /** ERC4626 CollateralTracker deposit(uint256 assets, address receiver). */
723
+ const DEPOSIT_SELECTOR = "0x6e553f65";
724
+ /** Uniswap UniversalRouter execute(bytes,bytes[],uint256). */
725
+ const EXECUTE_SELECTOR = "0x3593564c";
726
+ /**
727
+ * Scope CT.withdraw so tokens can only be pulled to the Safe: receiver == owner
728
+ * == Safe. Without this, a compromised bot key could withdraw the Safe's
729
+ * collateral to an arbitrary address — this is the critical cross-pool scope.
730
+ */
731
+ function buildWithdrawConditions(safe) {
732
+ const safeEq = addressEqualCompValue(safe);
733
+ return [
734
+ {
735
+ parent: 0,
736
+ paramType: ParameterType.Calldata,
737
+ operator: Operator.Matches,
738
+ compValue: "0x"
739
+ },
740
+ {
741
+ parent: 0,
742
+ paramType: ParameterType.Static,
743
+ operator: Operator.Pass,
744
+ compValue: "0x"
745
+ },
746
+ {
747
+ parent: 0,
748
+ paramType: ParameterType.Static,
749
+ operator: Operator.EqualTo,
750
+ compValue: safeEq
751
+ },
752
+ {
753
+ parent: 0,
754
+ paramType: ParameterType.Static,
755
+ operator: Operator.EqualTo,
756
+ compValue: safeEq
757
+ }
758
+ ];
759
+ }
760
+ /** Scope CT.deposit so the shares are credited to the Safe: receiver == Safe. */
761
+ function buildDepositConditions(safe) {
762
+ return [
763
+ {
764
+ parent: 0,
765
+ paramType: ParameterType.Calldata,
766
+ operator: Operator.Matches,
767
+ compValue: "0x"
768
+ },
769
+ {
770
+ parent: 0,
771
+ paramType: ParameterType.Static,
772
+ operator: Operator.Pass,
773
+ compValue: "0x"
774
+ },
775
+ {
776
+ parent: 0,
777
+ paramType: ParameterType.Static,
778
+ operator: Operator.EqualTo,
779
+ compValue: addressEqualCompValue(safe)
780
+ }
781
+ ];
782
+ }
783
+ /**
784
+ * Router `execute` is scoped with a calldata template — see
785
+ * apps/hedger-bot/scripts/lib/routerScope.ts (hedging-specific, not migrated).
786
+ */
787
+ const ROUTER_EXECUTE_SELECTOR_ONLY = EXECUTE_SELECTOR;
788
+
789
+ //#endregion
790
+ //#region src/zodiac/roles/maintenance.ts
791
+ /**
792
+ * Maintenance role: full `dispatchFrom` access — settle premium on, force-
793
+ * exercise, and liquidate third-party accounts using the Safe's capital.
794
+ * No adapter needed; the pool itself hash-validates the position lists.
795
+ *
796
+ * The only pin is `account != Safe` (Nor(EqualTo(safe))) so the maintenance
797
+ * key can never force-exercise or liquidate the Safe's own book.
798
+ * `positionIdListFrom` (the caller's solvency list) is intentionally
799
+ * unconstrained — the Safe may legitimately hold option positions.
800
+ *
801
+ * dispatchFrom is payable ⇒ ExecutionOptions.Send.
802
+ */
803
+ const MAINTENANCE_ROLE_KEY = roleKey("maintenance");
804
+ /** LeftRightUnsigned is a uint256 value type. */
805
+ const DISPATCH_FROM_SELECTOR = toFunctionSelector("dispatchFrom(uint256[],address,uint256[],uint256[],uint256)");
806
+ function buildDispatchFromConditions(safe) {
807
+ return [
808
+ {
809
+ parent: 0,
810
+ paramType: ParameterType.Calldata,
811
+ operator: Operator.Matches,
812
+ compValue: "0x"
813
+ },
814
+ {
815
+ parent: 0,
816
+ paramType: ParameterType.Array,
817
+ operator: Operator.Pass,
818
+ compValue: "0x"
819
+ },
820
+ {
821
+ parent: 0,
822
+ paramType: ParameterType.None,
823
+ operator: Operator.Nor,
824
+ compValue: "0x"
825
+ },
826
+ {
827
+ parent: 0,
828
+ paramType: ParameterType.Array,
829
+ operator: Operator.Pass,
830
+ compValue: "0x"
831
+ },
832
+ {
833
+ parent: 0,
834
+ paramType: ParameterType.Array,
835
+ operator: Operator.Pass,
836
+ compValue: "0x"
837
+ },
838
+ {
839
+ parent: 0,
840
+ paramType: ParameterType.Static,
841
+ operator: Operator.Pass,
842
+ compValue: "0x"
843
+ },
844
+ {
845
+ parent: 1,
846
+ paramType: ParameterType.Static,
847
+ operator: Operator.Pass,
848
+ compValue: "0x"
849
+ },
850
+ {
851
+ parent: 2,
852
+ paramType: ParameterType.Static,
853
+ operator: Operator.EqualTo,
854
+ compValue: addressEqualCompValue(safe)
855
+ },
856
+ {
857
+ parent: 3,
858
+ paramType: ParameterType.Static,
859
+ operator: Operator.Pass,
860
+ compValue: "0x"
861
+ },
862
+ {
863
+ parent: 4,
864
+ paramType: ParameterType.Static,
865
+ operator: Operator.Pass,
866
+ compValue: "0x"
867
+ }
868
+ ];
869
+ }
870
+ function buildMaintenanceRoleSteps(params) {
871
+ const key = params.roleKey ?? MAINTENANCE_ROLE_KEY;
872
+ return [
873
+ {
874
+ name: "assignRoles(maintenance member)",
875
+ functionName: "assignRoles",
876
+ args: [
877
+ params.member,
878
+ [key],
879
+ [true]
880
+ ]
881
+ },
882
+ {
883
+ name: "scopeTarget(pool)",
884
+ functionName: "scopeTarget",
885
+ args: [key, params.pool]
886
+ },
887
+ {
888
+ name: "scopeFunction(dispatchFrom, account != safe, Send)",
889
+ functionName: "scopeFunction",
890
+ args: [
891
+ key,
892
+ params.pool,
893
+ DISPATCH_FROM_SELECTOR,
894
+ buildDispatchFromConditions(params.safe),
895
+ ExecutionOptions.Send
896
+ ]
897
+ }
898
+ ];
899
+ }
900
+
901
+ //#endregion
902
+ //#region src/zodiac/roles/roller.ts
903
+ /**
904
+ * Roller role: close one position and reopen it identical-except-strike (roll
905
+ * out-of-range positions back into range). Enforced on-chain by the stateless
906
+ * `RollerCondition` adapter (strike-mask equality + one-burn-one-mint shape).
907
+ *
908
+ * The reopened size is bounded by `sizeCap` (0n = uncapped, leaving only
909
+ * dispatch's solvency check as the ceiling) — there is no pre-state oracle,
910
+ * so "same size as before" cannot be enforced.
911
+ */
912
+ const ROLLER_ROLE_KEY = roleKey("roller");
913
+ function buildRollerRoleSteps(params) {
914
+ return buildDispatchCustomRoleSteps({
915
+ roleName: "roller",
916
+ roleKey: params.roleKey ?? ROLLER_ROLE_KEY,
917
+ member: params.member,
918
+ pool: params.pool,
919
+ adapter: params.adapter,
920
+ extra: sizeCapExtra(params.sizeCap ?? 0n)
921
+ });
922
+ }
923
+
924
+ //#endregion
925
+ //#region src/zodiac/roles/sizeAdjuster.ts
926
+ /**
927
+ * Size-adjuster role: replace one position with an identical-except-optionRatio
928
+ * one — reduce a short whose long side was purchased, or grow a long as more
929
+ * options are sold. Enforced on-chain by the stateless `SizeAdjusterCondition`
930
+ * adapter (ratio-mask equality + one-burn-one-mint shape).
931
+ *
932
+ * Without a pre-state oracle the relative notional cap is not enforceable;
933
+ * set `sizeCap` (uint96, 0n = uncapped) to bound the mint size absolutely.
934
+ */
935
+ const SIZE_ADJUSTER_ROLE_KEY = roleKey("size-adjuster");
936
+ function buildSizeAdjusterRoleSteps(params) {
937
+ return buildDispatchCustomRoleSteps({
938
+ roleName: "size-adjuster",
939
+ roleKey: params.roleKey ?? SIZE_ADJUSTER_ROLE_KEY,
940
+ member: params.member,
941
+ pool: params.pool,
942
+ adapter: params.adapter,
943
+ extra: sizeCapExtra(params.sizeCap ?? 0n)
944
+ });
945
+ }
946
+
947
+ //#endregion
948
+ export { CANONICAL_ADAPTERS, DELEVERAGER_ROLE_KEY, DEPOSIT_SELECTOR, DISPATCH_FROM_SELECTOR, DISPATCH_SELECTOR, EXECUTE_SELECTOR, ExecutionOptions, LOAN_BITMASK_WINDOW_SHIFTS, MAINTENANCE_ROLE_KEY, Operator, ParameterType, ROLLER_ROLE_KEY, ROUTER_EXECUTE_SELECTOR_ONLY, SIZE_ADJUSTER_ROLE_KEY, WITHDRAW_SELECTOR, addressEqualCompValue, applyScopeSteps, buildDeleveragerDispatchConditions, buildDeleveragerRoleSteps, buildDepositConditions, buildDispatchCustomConditions, buildDispatchCustomRoleSteps, buildDispatchFromConditions, buildLoanOnlyDispatchConditions, buildMaintenanceRoleSteps, buildRollerRoleSteps, buildSizeAdjusterRoleSteps, buildWithdrawConditions, customCompValue, isPureLoanTokenId, legFieldMask, loanBitmaskCompValueAt, loanBitmaskCondition, loanWidthFieldsMask, optionRatioFieldsMask, roleKey, rolesV2Abi, sizeCapExtra, strikeFieldsMask };
949
+ //# sourceMappingURL=index.js.map