damm-sdk 1.4.35 → 1.4.37

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 (45) hide show
  1. package/dist/index.cjs +17187 -16747
  2. package/dist/index.cjs.map +84 -97
  3. package/dist/index.js +13222 -12265
  4. package/dist/index.js.map +77 -84
  5. package/dist/integrations/index.d.ts +1 -0
  6. package/dist/integrations/index.d.ts.map +1 -1
  7. package/dist/integrations/lagoonV1/delay.proxy.admin.d.ts +208 -0
  8. package/dist/integrations/lagoonV1/delay.proxy.admin.d.ts.map +1 -0
  9. package/dist/integrations/lagoonV1/index.d.ts +1 -0
  10. package/dist/integrations/lagoonV1/index.d.ts.map +1 -1
  11. package/dist/integrations/lagoonV1/lagoon.v1.d.ts +17 -0
  12. package/dist/integrations/lagoonV1/lagoon.v1.d.ts.map +1 -1
  13. package/dist/integrations/lagoonV2/addresses.d.ts +19 -0
  14. package/dist/integrations/lagoonV2/addresses.d.ts.map +1 -0
  15. package/dist/integrations/lagoonV2/factory.abi.d.ts +183 -0
  16. package/dist/integrations/lagoonV2/factory.abi.d.ts.map +1 -0
  17. package/dist/integrations/lagoonV2/index.d.ts +7 -0
  18. package/dist/integrations/lagoonV2/index.d.ts.map +1 -0
  19. package/dist/integrations/lagoonV2/lagoon.v2.d.ts +132 -0
  20. package/dist/integrations/lagoonV2/lagoon.v2.d.ts.map +1 -0
  21. package/dist/integrations/lagoonV2/lagoon.v2.permissions.d.ts +268 -0
  22. package/dist/integrations/lagoonV2/lagoon.v2.permissions.d.ts.map +1 -0
  23. package/dist/integrations/lagoonV2/lagoon.v2.setters.d.ts +293 -0
  24. package/dist/integrations/lagoonV2/lagoon.v2.setters.d.ts.map +1 -0
  25. package/dist/integrations/lagoonV2/vault.abi.d.ts +349 -0
  26. package/dist/integrations/lagoonV2/vault.abi.d.ts.map +1 -0
  27. package/dist/integrations/morphoVault/morpho.vault.d.ts +11 -0
  28. package/dist/integrations/morphoVault/morpho.vault.d.ts.map +1 -1
  29. package/dist/integrations/morphoVault/morpho.vault.v2.abi.d.ts +37 -0
  30. package/dist/integrations/morphoVault/morpho.vault.v2.abi.d.ts.map +1 -0
  31. package/package.json +1 -1
  32. package/src/integrations/index.ts +1 -0
  33. package/src/integrations/lagoonV1/delay.proxy.admin.ts +358 -0
  34. package/src/integrations/lagoonV1/index.ts +1 -0
  35. package/src/integrations/lagoonV1/lagoon.v1.ts +109 -36
  36. package/src/integrations/lagoonV2/addresses.ts +35 -0
  37. package/src/integrations/lagoonV2/factory.abi.ts +110 -0
  38. package/src/integrations/lagoonV2/index.ts +6 -0
  39. package/src/integrations/lagoonV2/lagoon.v2.permissions.ts +578 -0
  40. package/src/integrations/lagoonV2/lagoon.v2.setters.ts +521 -0
  41. package/src/integrations/lagoonV2/lagoon.v2.ts +345 -0
  42. package/src/integrations/lagoonV2/vault.abi.ts +479 -0
  43. package/src/integrations/morphoVault/morpho.vault.ts +45 -0
  44. package/src/integrations/morphoVault/morpho.vault.v2.abi.ts +23 -0
  45. package/src/lib/contractsRegistry.json +4 -2
@@ -0,0 +1,358 @@
1
+ /**
2
+ * DelayProxyAdmin upgrade encoders (M2 — slice 3 of the v0.5-on-OptinProxy continuity epic).
3
+ *
4
+ * The DelayProxyAdmin is deployed automatically by the LagoonVaultProxy constructor
5
+ * for every v0.5 vault. It is stored in the ERC-1967 admin slot of the proxy and
6
+ * implements a two-phase timelocked upgrade:
7
+ *
8
+ * Phase 1 — submitImplementation(address _implementation)
9
+ * Records `newImplementation` in storage and sets `implementationUpdateTime =
10
+ * block.timestamp + delay`. Owner-only.
11
+ * Selector: 0x657081b3 (submitImplementation(address))
12
+ *
13
+ * Phase 2 — upgradeAndCall(proxy, impl, data)
14
+ * After the timelock elapses, calls `proxy.upgradeToAndCall(newImplementation, data)`.
15
+ * The `impl` argument MUST equal the address that was passed to `submitImplementation`.
16
+ * The deployed contract reverts `ImplementationInconsistent(address expected)` if they
17
+ * differ. The encoder therefore passes the same v0.6 impl that was submitted in phase 1.
18
+ * For a storage-compatible v0.5→v0.6 swap pass empty calldata ("0x") — no
19
+ * reinitializer is needed (Lagoon guarantees storage layout compatibility).
20
+ * Selector: 0x9623609d (upgradeAndCall(address,address,bytes))
21
+ *
22
+ * Additional helpers:
23
+ * submitDelay(uint256 _delay) — schedule a delay change (timelocked by current delay)
24
+ * Selector: 0x432efade (submitDelay(uint256))
25
+ *
26
+ * Getter read helpers:
27
+ * newImplementation() — returns the pending impl submitted in phase 1
28
+ * Selector: 0x8b677b03 (newImplementation())
29
+ *
30
+ * delay() — returns the configured timelock in seconds
31
+ * Selector: 0x6a42b8f8
32
+ *
33
+ * v0.6 MaxCap unlock:
34
+ * After the upgrade, v0.6 storage slot for maxCap is zero (it was unused in v0.5).
35
+ * Every deposit therefore reverts MaxCapReached until the Safe owner calls
36
+ * updateMaxCap(<nominalCap>) on the vault. This is NOT a DelayProxyAdmin call —
37
+ * it's a v0.6 vault call. Use `lagoonV2UpdateMaxCapTrx` from lagoon.v2.setters for that.
38
+ *
39
+ * ── ABI verification ──────────────────────────────────────────────────────────
40
+ * Verified against DelayProxyAdmin.sol source (lagoon-v0/src/proxy/DelayProxyAdmin.sol)
41
+ * and confirmed via `cast sig` 2026-06-12:
42
+ * submitImplementation(address) = 0x657081b3
43
+ * newImplementation() = 0x8b677b03
44
+ * upgradeAndCall(address,address,bytes)= 0x9623609d
45
+ * delay() = 0x6a42b8f8
46
+ * implementationUpdateTime() = 0xf6b12cf9
47
+ * submitDelay(uint256) = 0x432efade
48
+ * owner() = 0x8da5cb5b
49
+ * ──────────────────────────────────────────────────────────────────────────────
50
+ */
51
+
52
+ import { encodeFunctionData, getAddress } from "viem";
53
+ import type { Address, Hex } from "viem";
54
+ import { createCall, type Call, type HexString, type Unwrapable } from "../..";
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Minimal ABI — only the functions we encode
58
+ // ---------------------------------------------------------------------------
59
+
60
+ const DELAY_PROXY_ADMIN_ABI = [
61
+ {
62
+ name: "submitImplementation",
63
+ type: "function",
64
+ inputs: [{ name: "impl", type: "address" }],
65
+ outputs: [],
66
+ stateMutability: "nonpayable",
67
+ },
68
+ {
69
+ name: "upgradeAndCall",
70
+ type: "function",
71
+ inputs: [
72
+ { name: "proxy", type: "address" },
73
+ { name: "impl", type: "address" },
74
+ { name: "data", type: "bytes" },
75
+ ],
76
+ outputs: [],
77
+ stateMutability: "payable",
78
+ },
79
+ {
80
+ name: "submitDelay",
81
+ type: "function",
82
+ inputs: [{ name: "newDelay", type: "uint256" }],
83
+ outputs: [],
84
+ stateMutability: "nonpayable",
85
+ },
86
+ {
87
+ // Public state variable getter — returns the pending implementation
88
+ // submitted in phase 1. Returns address(0) if no upgrade is queued.
89
+ // Selector: 0x8b677b03
90
+ name: "newImplementation",
91
+ type: "function",
92
+ inputs: [],
93
+ outputs: [{ name: "", type: "address" }],
94
+ stateMutability: "view",
95
+ },
96
+ {
97
+ // Public state variable getter — returns the enforced timelock in seconds.
98
+ // Selector: 0x6a42b8f8
99
+ name: "delay",
100
+ type: "function",
101
+ inputs: [],
102
+ outputs: [{ name: "", type: "uint256" }],
103
+ stateMutability: "view",
104
+ },
105
+ {
106
+ name: "owner",
107
+ type: "function",
108
+ inputs: [],
109
+ outputs: [{ name: "", type: "address" }],
110
+ stateMutability: "view",
111
+ },
112
+ ] as const;
113
+
114
+ // ---------------------------------------------------------------------------
115
+ // Types
116
+ // ---------------------------------------------------------------------------
117
+
118
+ /**
119
+ * Arguments for the two-phase timelocked upgrade of a v0.5→v0.6 vault.
120
+ */
121
+ export type DelayProxyAdminUpgradeArgs = Readonly<{
122
+ /** Address of the DelayProxyAdmin contract (stored in ERC-1967 admin slot). */
123
+ proxyAdmin: Address;
124
+ /** Address of the vault proxy being upgraded. */
125
+ proxy: Address;
126
+ /** New vault implementation address (e.g. Arb v0.6 impl). */
127
+ newImpl: Address;
128
+ }>;
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // Phase 1 — submitImplementation
132
+ // ---------------------------------------------------------------------------
133
+
134
+ /**
135
+ * Encodes `submitImplementation(address _implementation)` calldata.
136
+ * Selector: 0x657081b3
137
+ *
138
+ * Phase 1 of the timelocked upgrade. Records `newImpl` as `newImplementation`
139
+ * in storage and sets `implementationUpdateTime = block.timestamp + delay`.
140
+ * Owner-only. Emits `ImplementationUpdateSubmited`.
141
+ *
142
+ * After calling this, phase 2 (`upgradeAndCall`) can only execute after
143
+ * `block.timestamp >= implementationUpdateTime`.
144
+ *
145
+ * @param newImpl - The new implementation address to submit (e.g. v0.6 vault impl).
146
+ */
147
+ export const SubmitImplementationCalldata = ({ newImpl }: { readonly newImpl: Address }): HexString => {
148
+ return encodeFunctionData({
149
+ abi: DELAY_PROXY_ADMIN_ABI,
150
+ functionName: "submitImplementation",
151
+ args: [getAddress(newImpl)],
152
+ }) as HexString;
153
+ };
154
+
155
+ /**
156
+ * Wraps SubmitImplementationCalldata in a Call for Safe execution.
157
+ */
158
+ export const submitImplementationTrx = ({
159
+ proxyAdmin,
160
+ newImpl,
161
+ }: {
162
+ readonly proxyAdmin: Address;
163
+ readonly newImpl: Address;
164
+ }): Unwrapable<Call> => {
165
+ return createCall({
166
+ operation: 0,
167
+ to: proxyAdmin,
168
+ value: 0n,
169
+ data: SubmitImplementationCalldata({ newImpl }),
170
+ });
171
+ };
172
+
173
+ // ---------------------------------------------------------------------------
174
+ // Phase 2 — upgradeAndCall (empty calldata = storage-compatible swap)
175
+ // ---------------------------------------------------------------------------
176
+
177
+ /**
178
+ * Encodes `upgradeAndCall(address proxy, address impl, bytes data)` calldata.
179
+ * Selector: 0x9623609d
180
+ *
181
+ * Phase 2 of the timelocked upgrade. Executes the implementation swap.
182
+ *
183
+ * CONSTRAINT (enforced on-chain): `impl` MUST equal the address that was
184
+ * passed to `submitImplementation`. The DelayProxyAdmin reverts with
185
+ * `ImplementationMismatch` if they differ.
186
+ *
187
+ * Pass empty `data` ("0x") for a v0.5→v0.6 storage-compatible upgrade —
188
+ * no reinitializer is needed. Lagoon guarantees slot layout compatibility
189
+ * via `StorageCollision.t.sol`. The v0.6 storage field `maxCap` is simply
190
+ * zero after a clean upgrade; the vault owner must call `updateMaxCap`
191
+ * before the first deposit can succeed.
192
+ *
193
+ * This is a PAYABLE function — value is forwarded to the proxy's fallback
194
+ * if data is non-empty. For the empty-data case, value MUST be 0.
195
+ *
196
+ * @param args.proxy - The vault proxy address to upgrade.
197
+ * @param args.newImpl - The new implementation (must match phase-1 submission).
198
+ * @param args.data - Calldata forwarded to the new impl; use "0x" for v0.5→v0.6.
199
+ */
200
+ export const UpgradeAndCallCalldata = ({
201
+ proxy,
202
+ newImpl,
203
+ data = "0x",
204
+ }: {
205
+ readonly proxy: Address;
206
+ readonly newImpl: Address;
207
+ readonly data?: Hex;
208
+ }): HexString => {
209
+ return encodeFunctionData({
210
+ abi: DELAY_PROXY_ADMIN_ABI,
211
+ functionName: "upgradeAndCall",
212
+ args: [getAddress(proxy), getAddress(newImpl), data],
213
+ }) as HexString;
214
+ };
215
+
216
+ /**
217
+ * Wraps UpgradeAndCallCalldata in a Call for Safe execution.
218
+ * Value defaults to 0n (required for empty-data upgrades).
219
+ */
220
+ export const upgradeAndCallTrx = ({
221
+ proxyAdmin,
222
+ proxy,
223
+ newImpl,
224
+ data = "0x",
225
+ }: {
226
+ readonly proxyAdmin: Address;
227
+ readonly proxy: Address;
228
+ readonly newImpl: Address;
229
+ readonly data?: Hex;
230
+ }): Unwrapable<Call> => {
231
+ return createCall({
232
+ operation: 0,
233
+ to: proxyAdmin,
234
+ value: 0n,
235
+ data: UpgradeAndCallCalldata({ proxy, newImpl, data }),
236
+ });
237
+ };
238
+
239
+ // ---------------------------------------------------------------------------
240
+ // submitDelay — schedule a delay change (also timelocked)
241
+ // ---------------------------------------------------------------------------
242
+
243
+ /**
244
+ * Encodes `submitDelay(uint256 newDelay)` calldata.
245
+ * Selector: 0x432efade
246
+ *
247
+ * Schedules a change to the DelayProxyAdmin's timelock duration.
248
+ * The new delay is NOT applied immediately — it must be committed via
249
+ * `updateDelay()` (selector 0x0185921e) after the current delay elapses.
250
+ *
251
+ * On-chain bounds (verified from DelayProxyAdmin.sol source):
252
+ * MIN_DELAY = 86400s (1 day) — reverts DelayTooLow(86400) below this
253
+ * MAX_DELAY = 2592000s (30 days) — reverts DelayTooHigh(2592000) above this
254
+ *
255
+ * @param newDelay - New timelock duration in seconds. Must satisfy 86400 ≤ newDelay ≤ 2592000.
256
+ */
257
+ export const SubmitDelayCalldata = ({ newDelay }: { readonly newDelay: bigint }): HexString => {
258
+ const MIN_DELAY = 86400n; // 1 day in seconds
259
+ const MAX_DELAY = 2592000n; // 30 days in seconds
260
+ if (newDelay < MIN_DELAY) {
261
+ throw new Error(
262
+ `submitDelay: newDelay ${newDelay}s is below MIN_DELAY of ${MIN_DELAY}s (1 day). ` +
263
+ "The DelayProxyAdmin reverts on-chain with DelayTooLow(86400).",
264
+ );
265
+ }
266
+ if (newDelay > MAX_DELAY) {
267
+ throw new Error(
268
+ `submitDelay: newDelay ${newDelay}s exceeds MAX_DELAY of ${MAX_DELAY}s (30 days). ` +
269
+ "The DelayProxyAdmin reverts on-chain with DelayTooHigh(2592000).",
270
+ );
271
+ }
272
+ return encodeFunctionData({
273
+ abi: DELAY_PROXY_ADMIN_ABI,
274
+ functionName: "submitDelay",
275
+ args: [newDelay],
276
+ }) as HexString;
277
+ };
278
+
279
+ export const submitDelayTrx = ({
280
+ proxyAdmin,
281
+ newDelay,
282
+ }: {
283
+ readonly proxyAdmin: Address;
284
+ readonly newDelay: bigint;
285
+ }): Unwrapable<Call> => {
286
+ return createCall({
287
+ operation: 0,
288
+ to: proxyAdmin,
289
+ value: 0n,
290
+ data: SubmitDelayCalldata({ newDelay }),
291
+ });
292
+ };
293
+
294
+ // ---------------------------------------------------------------------------
295
+ // Getters (read helpers for off-chain use / test assertions)
296
+ // ---------------------------------------------------------------------------
297
+
298
+ /**
299
+ * ABI item for `newImplementation()` — the pending implementation submitted
300
+ * in phase 1. Returns `address(0)` if no upgrade is queued (after phase 2
301
+ * completes the field is reset to zero).
302
+ *
303
+ * Selector: 0x8b677b03
304
+ *
305
+ * @example
306
+ * const pending = await publicClient.readContract({
307
+ * address: proxyAdminAddress,
308
+ * abi: DELAY_PROXY_ADMIN_PENDING_IMPL_ABI,
309
+ * functionName: 'newImplementation',
310
+ * })
311
+ */
312
+ export const DELAY_PROXY_ADMIN_PENDING_IMPL_ABI = [
313
+ {
314
+ name: "newImplementation",
315
+ type: "function",
316
+ inputs: [],
317
+ outputs: [{ name: "", type: "address" }],
318
+ stateMutability: "view",
319
+ },
320
+ ] as const;
321
+
322
+ /**
323
+ * ABI item for `delay()` — returns the enforced timelock in seconds.
324
+ * This is the `delay` storage variable (public) that gates phase-2 execution.
325
+ *
326
+ * Selector: 0x6a42b8f8
327
+ *
328
+ * @example
329
+ * const timelockSeconds = await publicClient.readContract({
330
+ * address: proxyAdminAddress,
331
+ * abi: DELAY_PROXY_ADMIN_GET_MIN_DELAY_ABI,
332
+ * functionName: 'delay',
333
+ * })
334
+ */
335
+ export const DELAY_PROXY_ADMIN_GET_MIN_DELAY_ABI = [
336
+ {
337
+ name: "delay",
338
+ type: "function",
339
+ inputs: [],
340
+ outputs: [{ name: "", type: "uint256" }],
341
+ stateMutability: "view",
342
+ },
343
+ ] as const;
344
+
345
+ /**
346
+ * Returns the ABI item for `owner()` for use in viem readContract calls.
347
+ *
348
+ * Selector: 0x8da5cb5b
349
+ */
350
+ export const DELAY_PROXY_ADMIN_OWNER_ABI = [
351
+ {
352
+ name: "owner",
353
+ type: "function",
354
+ inputs: [],
355
+ outputs: [{ name: "", type: "address" }],
356
+ stateMutability: "view",
357
+ },
358
+ ] as const;
@@ -2,3 +2,4 @@ export { default as lagoonV1FactoryAbi } from "./factory.abi";
2
2
  export { default as lagoonV1VaultAbi } from "./vault.abi";
3
3
  export { default as lagoonV1SiloAbi } from "./silo.abi";
4
4
  export * from "./lagoon.v1";
5
+ export * from "./delay.proxy.admin";
@@ -1,9 +1,15 @@
1
1
  import { ethers } from "ethers";
2
2
  import { createCall, ZERO_ADDRESS, type Call, type HexString, type Unwrapable } from "../..";
3
- import { keccak256, defaultAbiCoder, solidityPack, getAddress } from "ethers/lib/utils";
4
- import type { Address } from "viem";
3
+ import { encodeAbiParameters, encodeFunctionData, encodePacked, getAddress, keccak256 } from "viem";
4
+ import type { Address, Hex } from "viem";
5
5
  import lagoonV1FactoryAbi from "./factory.abi.ts";
6
6
  import lagoonV1VaultAbi from "./vault.abi.ts";
7
+ import { LAGOON_VAULT_PROXY_CREATION_BYTECODE } from "../lagoonV2/lagoon.v2.ts";
8
+
9
+ // ethers/lib/utils imports removed: keccak256, defaultAbiCoder, solidityPack, getAddress
10
+ // are now sourced from viem (see imports above). The ethers utils were only used
11
+ // by the old OPTIN_PROXY_CREATION_BYTECODE predictor, which has been replaced
12
+ // by the LagoonVaultProxy predictor below.
7
13
 
8
14
  const factoryInterface = new ethers.utils.Interface(lagoonV1FactoryAbi);
9
15
  const vaultInterface = new ethers.utils.Interface(lagoonV1VaultAbi);
@@ -141,8 +147,14 @@ export const revokeFromVaultWhitelistTrx = ({
141
147
  });
142
148
  };
143
149
 
144
- const OPTIN_PROXY_CREATION_BYTECODE =
145
- "0x60c060405260405161154038038061154083398101604081905261002291610490565b61002c85856100a8565b8161003782826101b8565b5050828260405161004790610454565b6001600160a01b0390921682526020820152604001604051809103905ff080158015610075573d5f803e3d5ffd5b506001600160a01b031660805261009361008e60805190565b610216565b5050506001600160a01b031660a052506105f7565b5f6001600160a01b03831661011e57816001600160a01b03166345f55b3c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610117919061057b565b90506101b2565b6001600160a01b03821663f3c665f7610135610262565b856040518363ffffffff1660e01b8152600401610153929190610594565b602060405180830381865afa15801561016e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019291906105ae565b6101af5760405163474245d760e11b815260040160405180910390fd5b50815b92915050565b6101c18261027f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561020a5761020582826102e5565b505050565b610212610358565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61023f610379565b8260405161024e929190610594565b60405180910390a161025f81610398565b50565b5f61027a5f5f80516020611520833981519152610389565b905090565b806001600160a01b03163b5f036102b45780604051634c9c8ce360e01b81526004016102ab91906105cd565b60405180910390fd5b805f805160206115208339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b03168460405161030191906105e1565b5f60405180830381855af49150503d805f8114610339576040519150601f19603f3d011682016040523d82523d5f602084013e61033e565b606091505b50909250905061034f8583836103d5565b95945050505050565b34156103775760405163b398979f60e01b815260040160405180910390fd5b565b5f5f805160206115008339815191525b546001600160a01b0316919050565b6001600160a01b0381166103c1575f604051633173bdd160e11b81526004016102ab91906105cd565b805f805160206115008339815191526102c4565b6060826103ea576103e58261042b565b610424565b815115801561040157506001600160a01b0384163b155b156104215783604051639996b31560e01b81526004016102ab91906105cd565b50805b9392505050565b80511561043b5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b61095180610baf83390190565b80516001600160a01b0381168114610477575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f805f60a086880312156104a4575f80fd5b6104ad86610461565b94506104bb60208701610461565b93506104c960408701610461565b6060870151608088015191945092506001600160401b038111156104eb575f80fd5b8601601f810188136104fb575f80fd5b80516001600160401b038111156105145761051461047c565b604051601f8201601f19908116603f011681016001600160401b03811182821017156105425761054261047c565b6040528181528282016020018a1015610559575f80fd5b8160208401602083015e5f602083830101528093505050509295509295909350565b5f6020828403121561058b575f80fd5b61042482610461565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156105be575f80fd5b81518015158114610424575f80fd5b6001600160a01b0391909116815260200190565b5f82518060208501845e5f920191825250919050565b60805160a05161059361061c5f395f81816038015260f401525f607201526105935ff3fe60806040526004361061001d575f3560e01c806306433b1b14610027575b610025610070565b005b348015610032575f80fd5b5061005a7f000000000000000000000000000000000000000000000000000000000000000081565b60405161006791906103eb565b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036101c2575f356001600160e01b03191663278f794360e11b146100d2576040516334ad5dbb60e21b815260040160405180910390fd5b5f806100e136600481846103ff565b8101906100ee919061043a565b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f3c665f76101296101cc565b6040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529085166024820152604401602060405180830381865afa158015610173573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101979190610508565b6101b45760405163474245d760e11b815260040160405180910390fd5b6101be82826101f0565b5050565b6101ca61024a565b565b5f6101eb5f8051602061053e833981519152546001600160a01b031690565b905090565b6101f98261025a565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156102425761023d82826102bd565b505050565b6101be61032f565b6101ca6102556101cc565b61034e565b806001600160a01b03163b5f0361028f5780604051634c9c8ce360e01b815260040161028691906103eb565b60405180910390fd5b5f8051602061053e83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102d99190610527565b5f60405180830381855af49150503d805f8114610311576040519150601f19603f3d011682016040523d82523d5f602084013e610316565b606091505b509150915061032685838361036c565b95945050505050565b34156101ca5760405163b398979f60e01b815260040160405180910390fd5b365f80375f80365f845af43d5f803e808015610368573d5ff35b3d5ffd5b6060826103815761037c826103c2565b6103bb565b815115801561039857506001600160a01b0384163b155b156103b85783604051639996b31560e01b815260040161028691906103eb565b50805b9392505050565b8051156103d25780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0391909116815260200190565b5f808585111561040d575f80fd5b83861115610419575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561044b575f80fd5b82356001600160a01b0381168114610461575f80fd5b915060208301356001600160401b0381111561047b575f80fd5b8301601f8101851361048b575f80fd5b80356001600160401b038111156104a4576104a4610426565b604051601f8201601f19908116603f011681016001600160401b03811182821017156104d2576104d2610426565b6040528181528282016020018710156104e9575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610518575f80fd5b815180151581146103bb575f80fd5b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122054a7e97969c29f5ce4c21e7feeef7fb958d11e31d8152e7ae4ea8a848a71848c64736f6c634300081a0033608060405234801561000f575f80fd5b5060405161095138038061095183398101604081905261002e91610158565b81806001600160a01b03811661005e57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006781610109565b5050620151808110156100925760405163013ccc8d60e01b8152620151806004820152602401610055565b62278d008111156100bb57604051630b94129b60e31b815262278d006004820152602401610055565b5f1960018190556003556005819055604080518281525f60208201527fa580b4a9812995ffed1b336481c3f3bfeb3414df9f587a9d73856bab25aa4eee910160405180910390a1505061018f565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f8060408385031215610169575f80fd5b82516001600160a01b038116811461017f575f80fd5b6020939093015192949293505050565b6107b58061019c5f395ff3fe6080604052600436106100b7575f3560e01c8063033f8dbc146100bb5780634125ff90146100e3578063432efade146100f9578063554f94db1461011a578063657081b31461012e5780636a42b8f81461014d578063715018a6146101625780638b677b03146101765780638da5cb5b146101a25780639623609d146101b65780639f81aed7146101c9578063a36f141c146101df578063ad3cb1cc146101f4578063f2fde38b14610231578063f6b12cf914610250575b5f80fd5b3480156100c6575f80fd5b506100d060045481565b6040519081526020015b60405180910390f35b3480156100ee575f80fd5b506100d062278d0081565b348015610104575f80fd5b506101186101133660046105a6565b610265565b005b348015610125575f80fd5b50610118610326565b348015610139575f80fd5b506101186101483660046105d1565b6103a8565b348015610158575f80fd5b506100d060055481565b34801561016d575f80fd5b50610118610420565b348015610181575f80fd5b50600254610195906001600160a01b031681565b6040516100da91906105f3565b3480156101ad575f80fd5b50610195610433565b6101186101c436600461061b565b610441565b3480156101d4575f80fd5b506100d06201518081565b3480156101ea575f80fd5b506100d060035481565b3480156101ff575f80fd5b50610224604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100da919061071d565b34801561023c575f80fd5b5061011861024b3660046105d1565b6104e8565b34801561025b575f80fd5b506100d060015481565b61026d610525565b6201518081101561029b5760405163013ccc8d60e01b81526201518060048201526024015b60405180910390fd5b62278d008111156102c457604051630b94129b60e31b815262278d006004820152602401610292565b60048190556005546102d6904261072f565b60038190556005546004546040805192835260208301919091528101919091527fab7d3921ca5710b1f874b995128f2d434b8b28080cc90e5b7ae542d01a41dd6e9060600160405180910390a150565b61032e610525565b60035442101561035157604051634040f3a760e01b815260040160405180910390fd5b7fa580b4a9812995ffed1b336481c3f3bfeb3414df9f587a9d73856bab25aa4eee60045460055460405161038f929190918252602082015260400190565b60405180910390a1600480546005555f90555f19600355565b6103b0610525565b600280546001600160a01b0319166001600160a01b0383161790556005546103d8904261072f565b60018190556002546040519182526001600160a01b0316907fb995d606597d17deae0e0b28f4668c00c67c22d7bed7b95db2a5ac7f1b96aa2b9060200160405180910390a250565b610428610525565b6104315f610557565b565b5f546001600160a01b031690565b610449610525565b60015442101561046c57604051634040f3a760e01b815260040160405180910390fd5b60025460405163278f794360e11b81526001600160a01b0380861692634f1ef2869234926104a09216908690600401610754565b5f604051808303818588803b1580156104b7575f80fd5b505af11580156104c9573d5f803e3d5ffd5b5050600280546001600160a01b031916905550505f1960015550505050565b6104f0610525565b6001600160a01b038116610519575f604051631e4fbdf760e01b815260040161029291906105f3565b61052281610557565b50565b3361052e610433565b6001600160a01b031614610431573360405163118cdaa760e01b815260040161029291906105f3565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156105b6575f80fd5b5035919050565b6001600160a01b0381168114610522575f80fd5b5f602082840312156105e1575f80fd5b81356105ec816105bd565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121561062d575f80fd5b8335610638816105bd565b92506020840135610648816105bd565b915060408401356001600160401b03811115610662575f80fd5b8401601f81018613610672575f80fd5b80356001600160401b0381111561068b5761068b610607565b604051601f8201601f19908116603f011681016001600160401b03811182821017156106b9576106b9610607565b6040528181528282016020018810156106d0575f80fd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6105ec60208301846106ef565b8082018082111561074e57634e487b7160e01b5f52601160045260245ffd5b92915050565b6001600160a01b03831681526040602082018190525f90610777908301846106ef565b94935050505056fea2646970667358221220e27ebccd00d28ef8e1c57bfd0e4ffadef9ac6d95a3f3cc646f6f86755492f76564736f6c634300081a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
150
+ // OPTIN_PROXY_CREATION_BYTECODE was the protocol-v2 OptinProxy creation bytecode.
151
+ // It has been REMOVED. The v0.5 address predictor now uses LAGOON_VAULT_PROXY_CREATION_BYTECODE
152
+ // (the protocol-v3 proxy, imported from lagoonV2/lagoon.v2.ts) to produce addresses
153
+ // that match what the v3 OptinProxyFactory deploys.
154
+ //
155
+ // The old bytecode is retained here as a comment solely for provenance / debugging existing
156
+ // beacon-proxy addresses that were deployed before this migration:
157
+ // const OPTIN_PROXY_CREATION_BYTECODE = "0x60c060405260405161154038038061154083398101604081905261002291610490565b61002c85856100a8565b8161003782826101b8565b5050828260405161004790610454565b6001600160a01b0390921682526020820152604001604051809103905ff080158015610075573d5f803e3d5ffd5b506001600160a01b031660805261009361008e60805190565b610216565b5050506001600160a01b031660a052506105f7565b5f6001600160a01b03831661011e57816001600160a01b03166345f55b3c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610117919061057b565b90506101b2565b6001600160a01b03821663f3c665f7610135610262565b856040518363ffffffff1660e01b8152600401610153929190610594565b602060405180830381865afa15801561016e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019291906105ae565b6101af5760405163474245d760e11b815260040160405180910390fd5b50815b92915050565b6101c18261027f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561020a5761020582826102e5565b505050565b610212610358565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61023f610379565b8260405161024e929190610594565b60405180910390a161025f81610398565b50565b5f61027a5f5f80516020611520833981519152610389565b905090565b806001600160a01b03163b5f036102b45780604051634c9c8ce360e01b81526004016102ab91906105cd565b60405180910390fd5b805f805160206115208339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b03168460405161030191906105e1565b5f60405180830381855af49150503d805f8114610339576040519150601f19603f3d011682016040523d82523d5f602084013e61033e565b606091505b50909250905061034f8583836103d5565b95945050505050565b34156103775760405163b398979f60e01b815260040160405180910390fd5b565b5f5f805160206115008339815191525b546001600160a01b0316919050565b6001600160a01b0381166103c1575f604051633173bdd160e11b81526004016102ab91906105cd565b805f805160206115008339815191526102c4565b6060826103ea576103e58261042b565b610424565b815115801561040157506001600160a01b0384163b155b156104215783604051639996b31560e01b81526004016102ab91906105cd565b50805b9392505050565b80511561043b5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b61095180610baf83390190565b80516001600160a01b0381168114610477575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f805f60a086880312156104a4575f80fd5b6104ad86610461565b94506104bb60208701610461565b93506104c960408701610461565b6060870151608088015191945092506001600160401b038111156104eb575f80fd5b8601601f810188136104fb575f80fd5b80516001600160401b038111156105145761051461047c565b604051601f8201601f19908116603f011681016001600160401b03811182821017156105425761054261047c565b6040528181528282016020018a1015610559575f80fd5b8160208401602083015e5f602083830101528093505050509295509295909350565b5f6020828403121561058b575f80fd5b61042482610461565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156105be575f80fd5b81518015158114610424575f80fd5b6001600160a01b0391909116815260200190565b5f82518060208501845e5f920191825250919050565b60805160a05161059361061c5f395f81816038015260f401525f607201526105935ff3fe60806040526004361061001d575f3560e01c806306433b1b14610027575b610025610070565b005b348015610032575f80fd5b5061005a7f000000000000000000000000000000000000000000000000000000000000000081565b60405161006791906103eb565b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036101c2575f356001600160e01b03191663278f794360e11b146100d2576040516334ad5dbb60e21b815260040160405180910390fd5b5f806100e136600481846103ff565b8101906100ee919061043a565b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f3c665f76101296101cc565b6040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529085166024820152604401602060405180830381865afa158015610173573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101979190610508565b6101b45760405163474245d760e11b815260040160405180910390fd5b6101be82826101f0565b5050565b6101ca61024a565b565b5f6101eb5f8051602061053e833981519152546001600160a01b031690565b905090565b6101f98261025a565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156102425761023d82826102bd565b505050565b6101be61032f565b6101ca6102556101cc565b61034e565b806001600160a01b03163b5f0361028f5780604051634c9c8ce360e01b815260040161028691906103eb565b60405180910390fd5b5f8051602061053e83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102d99190610527565b5f60405180830381855af49150503d805f8114610311576040519150601f19603f3d011682016040523d82523d5f602084013e610316565b606091505b509150915061032685838361036c565b95945050505050565b34156101ca5760405163b398979f60e01b815260040160405180910390fd5b365f80375f80365f845af43d5f803e808015610368573d5ff35b3d5ffd5b6060826103815761037c826103c2565b6103bb565b815115801561039857506001600160a01b0384163b155b156103b85783604051639996b31560e01b815260040161028691906103eb565b50805b9392505050565b8051156103d25780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0391909116815260200190565b5f808585111561040d575f80fd5b83861115610419575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561044b575f80fd5b82356001600160a01b0381168114610461575f80fd5b915060208301356001600160401b0381111561047b575f80fd5b8301601f8101851361048b575f80fd5b80356001600160401b038111156104a4576104a4610426565b604051601f8201601f19908116603f011681016001600160401b03811182821017156104d2576104d2610426565b6040528181528282016020018710156104e9575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610518575f80fd5b815180151581146103bb575f80fd5b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122054a7e97969c29f5ce4c21e7feeef7fb958d11e31d8152e7ae4ea8a848a71848c64736f6c634300081a0033608060405234801561000f575f80fd5b5060405161095138038061095183398101604081905261002e91610158565b81806001600160a01b03811661005e57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61006781610109565b5050620151808110156100925760405163013ccc8d60e01b8152620151806004820152602401610055565b62278d008111156100bb57604051630b94129b60e31b815262278d006004820152602401610055565b5f1960018190556003556005819055604080518281525f60208201527fa580b4a9812995ffed1b336481c3f3bfeb3414df9f587a9d73856bab25aa4eee910160405180910390a1505061018f565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f8060408385031215610169575f80fd5b82516001600160a01b038116811461017f575f80fd5b6020939093015192949293505050565b6107b58061019c5f395ff3fe6080604052600436106100b7575f3560e01c8063033f8dbc146100bb5780634125ff90146100e3578063432efade146100f9578063554f94db1461011a578063657081b31461012e5780636a42b8f81461014d578063715018a6146101625780638b677b03146101765780638da5cb5b146101a25780639623609d146101b65780639f81aed7146101c9578063a36f141c146101df578063ad3cb1cc146101f4578063f2fde38b14610231578063f6b12cf914610250575b5f80fd5b3480156100c6575f80fd5b506100d060045481565b6040519081526020015b60405180910390f35b3480156100ee575f80fd5b506100d062278d0081565b348015610104575f80fd5b506101186101133660046105a6565b610265565b005b348015610125575f80fd5b50610118610326565b348015610139575f80fd5b506101186101483660046105d1565b6103a8565b348015610158575f80fd5b506100d060055481565b34801561016d575f80fd5b50610118610420565b348015610181575f80fd5b50600254610195906001600160a01b031681565b6040516100da91906105f3565b3480156101ad575f80fd5b50610195610433565b6101186101c436600461061b565b610441565b3480156101d4575f80fd5b506100d06201518081565b3480156101ea575f80fd5b506100d060035481565b3480156101ff575f80fd5b50610224604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100da919061071d565b34801561023c575f80fd5b5061011861024b3660046105d1565b6104e8565b34801561025b575f80fd5b506100d060015481565b61026d610525565b6201518081101561029b5760405163013ccc8d60e01b81526201518060048201526024015b60405180910390fd5b62278d008111156102c457604051630b94129b60e31b815262278d006004820152602401610292565b60048190556005546102d6904261072f565b60038190556005546004546040805192835260208301919091528101919091527fab7d3921ca5710b1f874b995128f2d434b8b28080cc90e5b7ae542d01a41dd6e9060600160405180910390a150565b61032e610525565b60035442101561035157604051634040f3a760e01b815260040160405180910390fd5b7fa580b4a9812995ffed1b336481c3f3bfeb3414df9f587a9d73856bab25aa4eee60045460055460405161038f929190918252602082015260400190565b60405180910390a1600480546005555f90555f19600355565b6103b0610525565b600280546001600160a01b0319166001600160a01b0383161790556005546103d8904261072f565b60018190556002546040519182526001600160a01b0316907fb995d606597d17deae0e0b28f4668c00c67c22d7bed7b95db2a5ac7f1b96aa2b9060200160405180910390a250565b610428610525565b6104315f610557565b565b5f546001600160a01b031690565b610449610525565b60015442101561046c57604051634040f3a760e01b815260040160405180910390fd5b60025460405163278f794360e11b81526001600160a01b0380861692634f1ef2869234926104a09216908690600401610754565b5f604051808303818588803b1580156104b7575f80fd5b505af11580156104c9573d5f803e3d5ffd5b5050600280546001600160a01b031916905550505f1960015550505050565b6104f0610525565b6001600160a01b038116610519575f604051631e4fbdf760e01b815260040161029291906105f3565b61052281610557565b50565b3361052e610433565b6001600160a01b031614610431573360405163118cdaa760e01b815260040161029291906105f3565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156105b6575f80fd5b5035919050565b6001600160a01b0381168114610522575f80fd5b5f602082840312156105e1575f80fd5b81356105ec816105bd565b9392505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121561062d575f80fd5b8335610638816105bd565b92506020840135610648816105bd565b915060408401356001600160401b03811115610662575f80fd5b8401601f81018613610672575f80fd5b80356001600160401b0381111561068b5761068b610607565b604051601f8201601f19908116603f011681016001600160401b03811182821017156106b9576106b9610607565b6040528181528282016020018810156106d0575f80fd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6105ec60208301846106ef565b8082018082111561074e57634e487b7160e01b5f52601160045260245ffd5b92915050565b6001600160a01b03831681526040602082018190525f90610777908301846106ef565b94935050505056fea2646970667358221220e27ebccd00d28ef8e1c57bfd0e4ffadef9ac6d95a3f3cc646f6f86755492f76564736f6c634300081a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
146
158
 
147
159
  // Pause vault operations (GUARDIAN action)
148
160
  // Halts all deposit/redeem operations
@@ -210,6 +222,57 @@ export const closeVaultTrx = ({
210
222
  });
211
223
  };
212
224
 
225
+ // ABI type for the 12-field v0.5 InitStruct (matches Solidity ABI encoding order)
226
+ const V05_INIT_STRUCT_ABI_TYPE = {
227
+ type: "tuple",
228
+ components: [
229
+ { name: "underlying", type: "address" },
230
+ { name: "name", type: "string" },
231
+ { name: "symbol", type: "string" },
232
+ { name: "safe", type: "address" },
233
+ { name: "whitelistManager", type: "address" },
234
+ { name: "valuationManager", type: "address" },
235
+ { name: "admin", type: "address" },
236
+ { name: "feeReceiver", type: "address" },
237
+ { name: "managementRate", type: "uint16" },
238
+ { name: "performanceRate", type: "uint16" },
239
+ { name: "enableWhitelist", type: "bool" },
240
+ { name: "rateUpdateCooldown", type: "uint256" },
241
+ ],
242
+ } as const;
243
+
244
+ // initialize(bytes _data, address _feeRegistry, address _wrappedNativeToken)
245
+ const V05_INITIALIZE_ABI = [
246
+ {
247
+ name: "initialize",
248
+ type: "function",
249
+ inputs: [
250
+ { name: "_data", type: "bytes" },
251
+ { name: "_feeRegistry", type: "address" },
252
+ { name: "_wrappedNativeToken", type: "address" },
253
+ ],
254
+ outputs: [],
255
+ stateMutability: "nonpayable",
256
+ },
257
+ ] as const;
258
+
259
+ /**
260
+ * Computes the deterministic CREATE2 vault address for a v0.5 Lagoon vault
261
+ * deployed via the protocol-v3 OptinProxyFactory.
262
+ *
263
+ * The v3 factory deploys `new LagoonVaultProxy{salt: salt}(logic, registry, initialOwner, initialDelay, call_data)`.
264
+ * The CREATE2 address is: keccak256(0xff ++ factory ++ salt ++ keccak256(initCode))[-20:]
265
+ * where initCode = LAGOON_VAULT_PROXY_CREATION_BYTECODE + abi.encode(logic, registry, initialOwner, initialDelay, call_data)
266
+ *
267
+ * The proxy is logic-agnostic: the same LagoonVaultProxy bytecode is used for v0.5 and v0.6.
268
+ * Only the inner `call_data` (initialize calldata) differs between versions.
269
+ *
270
+ * @param factoryAddress - The v3 OptinProxyFactory address (per-chain)
271
+ * @param registry - The shared fee registry address
272
+ * @param wrappedNativeToken - The wrapped native token address (per-chain)
273
+ * @param initStruct - The 12-field v0.5 InitStruct (logic, salt, and all vault params)
274
+ * @returns EIP-55 checksummed address of the vault that would be deployed
275
+ */
213
276
  export const calculateDeterministicVaultAddress = ({
214
277
  factoryAddress,
215
278
  registry,
@@ -221,47 +284,57 @@ export const calculateDeterministicVaultAddress = ({
221
284
  wrappedNativeToken: Address;
222
285
  initStruct: LagoonFactoryCreateVaultProxyArgs;
223
286
  }): Address => {
224
- const initEncoded = defaultAbiCoder.encode(
225
- ["tuple(address,string,string,address,address,address,address,address,uint16,uint16,bool,uint256)"],
287
+ // Step 1: ABI-encode the 12-field v0.5 InitStruct as a tuple
288
+ const encodedInitStruct = encodeAbiParameters(
289
+ [V05_INIT_STRUCT_ABI_TYPE],
226
290
  [
227
- [
228
- initStruct.underlying,
229
- initStruct.name,
230
- initStruct.symbol,
231
- initStruct.safe,
232
- initStruct.enableWhitelist ? initStruct.whitelistManager : ZERO_ADDRESS,
233
- initStruct.valuationManager,
234
- initStruct.admin,
235
- initStruct.feeReceiver,
236
- initStruct.managementRate,
237
- initStruct.performanceRate,
238
- initStruct.enableWhitelist,
239
- initStruct.rateUpdateCooldown,
240
- ],
291
+ {
292
+ underlying: initStruct.underlying,
293
+ name: initStruct.name,
294
+ symbol: initStruct.symbol,
295
+ safe: initStruct.safe,
296
+ whitelistManager: initStruct.enableWhitelist ? initStruct.whitelistManager : (ZERO_ADDRESS as Address),
297
+ valuationManager: initStruct.valuationManager,
298
+ admin: initStruct.admin,
299
+ feeReceiver: initStruct.feeReceiver,
300
+ managementRate: Number(initStruct.managementRate),
301
+ performanceRate: Number(initStruct.performanceRate),
302
+ enableWhitelist: initStruct.enableWhitelist,
303
+ rateUpdateCooldown: initStruct.rateUpdateCooldown,
304
+ },
241
305
  ],
242
306
  );
243
307
 
244
- // 2️⃣ Encode the IVault.initialize call (bytes _data for OptinProxy constructor)
245
- const iface = new ethers.utils.Interface([
246
- "function initialize(bytes data, address feeRegistry, address wrappedNativeToken)",
247
- ]);
248
- const initCall = iface.encodeFunctionData("initialize", [initEncoded, registry, wrappedNativeToken]);
308
+ // Step 2: Encode the initialize(bytes,address,address) call (the call_data the proxy receives)
309
+ const callData = encodeFunctionData({
310
+ abi: V05_INITIALIZE_ABI,
311
+ functionName: "initialize",
312
+ args: [encodedInitStruct, registry, wrappedNativeToken],
313
+ });
249
314
 
250
- // 3️⃣ Encode the OptinProxy constructor arguments
251
- const constructorEncoded = defaultAbiCoder.encode(
252
- ["address", "address", "address", "uint256", "bytes"], // (logic, registry, owner, delay, data)
253
- [initStruct.logic, registry, initStruct.initialOwner, initStruct.initialDelay, initCall],
315
+ // Step 3: ABI-encode the LagoonVaultProxy constructor args
316
+ // Constructor signature: (address logic, address registry, address initialOwner, uint256 initialDelay, bytes call_data)
317
+ const constructorEncoded = encodeAbiParameters(
318
+ [
319
+ { name: "logic", type: "address" },
320
+ { name: "registry", type: "address" },
321
+ { name: "initialOwner", type: "address" },
322
+ { name: "initialDelay", type: "uint256" },
323
+ { name: "call_data", type: "bytes" },
324
+ ],
325
+ [initStruct.logic, registry, initStruct.initialOwner, initStruct.initialDelay, callData],
254
326
  );
255
327
 
256
- // 4️⃣ Build the CREATE2 init code (creation bytecode + encoded constructor args)
257
- const initCode = OPTIN_PROXY_CREATION_BYTECODE + constructorEncoded.slice(2);
328
+ // Step 4: Full init code = LagoonVaultProxy creation bytecode + abi.encode(constructor args)
329
+ const initCode = (LAGOON_VAULT_PROXY_CREATION_BYTECODE + constructorEncoded.slice(2)) as Hex;
330
+ const initCodeHash = keccak256(initCode);
258
331
 
259
- // 5️⃣ Compute CREATE2 address
260
- const create2Inputs = solidityPack(
332
+ // Step 5: CREATE2 address = keccak256(0xff ++ factory ++ salt ++ keccak256(initCode))[-20:]
333
+ const create2Input = encodePacked(
261
334
  ["bytes1", "address", "bytes32", "bytes32"],
262
- ["0xff", factoryAddress, initStruct.salt, keccak256(initCode)],
335
+ ["0xff", factoryAddress, initStruct.salt as Hex, initCodeHash],
263
336
  );
264
337
 
265
- const computedAddress = `0x${keccak256(create2Inputs).slice(-40)}`;
266
- return getAddress(computedAddress) as Address;
338
+ const hash = keccak256(create2Input);
339
+ return getAddress(`0x${hash.slice(-40)}`) as Address;
267
340
  };
@@ -0,0 +1,35 @@
1
+ import type { Address } from "viem";
2
+
3
+ /**
4
+ * Per-chain addresses for the Lagoon v0.6 stack.
5
+ * Verified on-chain 2026-06-08.
6
+ *
7
+ * factory: The v3 Lagoon factory proxy (deploys via CREATE2, hosts registry() + wrappedNativeToken() views).
8
+ * vaultImpl: The v0.6 vault implementation logic address. MUST be passed explicitly as `logic` in
9
+ * createVaultProxy — never address(0), which silently falls back to v0.5.0.
10
+ * registry: Shared fee registry (same address on all chains).
11
+ * wrappedNative: Wrapped native token (WETH on ETH/Arb).
12
+ */
13
+ export type LagoonV2ChainAddresses = Readonly<{
14
+ factory: Address;
15
+ vaultImpl: Address;
16
+ registry: Address;
17
+ wrappedNative: Address;
18
+ }>;
19
+
20
+ export const LAGOON_V2_ADDRESSES: Readonly<Record<number, LagoonV2ChainAddresses>> = {
21
+ /** Arbitrum One */
22
+ 42161: {
23
+ factory: "0x9De724B0efEe0FbA07FE21a16B9Bf9bBb5204Fb4",
24
+ vaultImpl: "0x3f5A9e1D82c595d14bA93c97eB8a77928cFdee70",
25
+ registry: "0x6dA4D1859bA1d02D095D2246142CdAd52233e27C",
26
+ wrappedNative: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
27
+ },
28
+ /** Ethereum Mainnet */
29
+ 1: {
30
+ factory: "0x8D6f5479B14348186faE9BC7E636e947c260f9B1",
31
+ vaultImpl: "0x6C77c47FB8168E22976C3B0338CB1769c952249f",
32
+ registry: "0x6dA4D1859bA1d02D095D2246142CdAd52233e27C",
33
+ wrappedNative: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
34
+ },
35
+ } as const;