@black-market/sdk 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +96 -79
  2. package/dist/lifecycle/abi.d.ts +1 -0
  3. package/dist/lifecycle/abi.d.ts.map +1 -1
  4. package/dist/lifecycle/abi.js +1 -0
  5. package/dist/lifecycle/abi.js.map +1 -1
  6. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts +71 -0
  7. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts.map +1 -0
  8. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js +73 -0
  9. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js.map +1 -0
  10. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts +71 -0
  11. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts.map +1 -0
  12. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js +73 -0
  13. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js.map +1 -0
  14. package/dist/lifecycle/index.d.ts +1 -0
  15. package/dist/lifecycle/index.d.ts.map +1 -1
  16. package/dist/lifecycle/index.js +1 -0
  17. package/dist/lifecycle/index.js.map +1 -1
  18. package/dist/lifecycle/markets.d.ts +3 -1
  19. package/dist/lifecycle/markets.d.ts.map +1 -1
  20. package/dist/lifecycle/markets.js +20 -3
  21. package/dist/lifecycle/markets.js.map +1 -1
  22. package/dist/lifecycle/planner.d.ts.map +1 -1
  23. package/dist/lifecycle/planner.js +101 -46
  24. package/dist/lifecycle/planner.js.map +1 -1
  25. package/dist/lifecycle/presets.d.ts +4 -2
  26. package/dist/lifecycle/presets.d.ts.map +1 -1
  27. package/dist/lifecycle/presets.js +11 -4
  28. package/dist/lifecycle/presets.js.map +1 -1
  29. package/dist/lifecycle/progress.d.ts +3 -1
  30. package/dist/lifecycle/progress.d.ts.map +1 -1
  31. package/dist/lifecycle/progress.js +145 -59
  32. package/dist/lifecycle/progress.js.map +1 -1
  33. package/dist/lifecycle/rpc.d.ts +8 -2
  34. package/dist/lifecycle/rpc.d.ts.map +1 -1
  35. package/dist/lifecycle/rpc.js +165 -9
  36. package/dist/lifecycle/rpc.js.map +1 -1
  37. package/dist/lifecycle/simulation.d.ts +1 -1
  38. package/dist/lifecycle/simulation.d.ts.map +1 -1
  39. package/dist/lifecycle/simulation.js +15 -11
  40. package/dist/lifecycle/simulation.js.map +1 -1
  41. package/dist/lifecycle/types.d.ts +23 -1
  42. package/dist/lifecycle/types.d.ts.map +1 -1
  43. package/dist/lifecycle/types.js.map +1 -1
  44. package/dist/lifecycle/ufg-abi.d.ts +2386 -0
  45. package/dist/lifecycle/ufg-abi.d.ts.map +1 -0
  46. package/dist/lifecycle/ufg-abi.js +171 -0
  47. package/dist/lifecycle/ufg-abi.js.map +1 -0
  48. package/dist/lifecycle/ufg-config.d.ts +38 -0
  49. package/dist/lifecycle/ufg-config.d.ts.map +1 -0
  50. package/dist/lifecycle/ufg-config.js +75 -0
  51. package/dist/lifecycle/ufg-config.js.map +1 -0
  52. package/dist/lifecycle/ufg.d.ts +21 -0
  53. package/dist/lifecycle/ufg.d.ts.map +1 -0
  54. package/dist/lifecycle/ufg.js +98 -0
  55. package/dist/lifecycle/ufg.js.map +1 -0
  56. package/docs/launch-lifecycle.md +611 -1363
  57. package/docs/reference.md +332 -0
  58. package/examples/.env.example +3 -2
  59. package/examples/README.md +172 -539
  60. package/examples/launch-example-support.ts +11 -3
  61. package/examples/launch-example.ts +1 -1
  62. package/examples/launch-lifecycle-smoke.ts +1 -1
  63. package/examples/ufg-launch-config.ts +31 -0
  64. package/package.json +1 -1
  65. package/src/lifecycle/abi.ts +1 -0
  66. package/src/lifecycle/deployments/ufg-dynamic-pool-20261021.ts +74 -0
  67. package/src/lifecycle/deployments/ufg-fixed-pool-20261021.ts +74 -0
  68. package/src/lifecycle/index.ts +1 -0
  69. package/src/lifecycle/markets.ts +16 -3
  70. package/src/lifecycle/planner.ts +95 -45
  71. package/src/lifecycle/presets.ts +11 -4
  72. package/src/lifecycle/progress.ts +131 -51
  73. package/src/lifecycle/rpc.ts +158 -10
  74. package/src/lifecycle/simulation.ts +14 -10
  75. package/src/lifecycle/types.ts +15 -2
  76. package/src/lifecycle/ufg-abi.ts +173 -0
  77. package/src/lifecycle/ufg-config.ts +77 -0
  78. package/src/lifecycle/ufg.ts +86 -0
@@ -1,11 +1,12 @@
1
1
  import { decodeErrorResult, decodeEventLog, decodeFunctionResult, encodeFunctionData, encodeFunctionResult, parseAbi, toHex, type Hex } from "viem";
2
2
  import { fixedFeePoolHookV1Abi, launchLifecycleAbi, lifecycleErc20Abi } from "./abi.js";
3
3
  import { hashLaunchIdentity, hashLaunchPlan, LifecyclePhase, type LaunchPlanV1, type LaunchProgressV1, type LaunchReceiptV1 } from "./schema.js";
4
- import { assertLifecycleBlock, assertLifecycleReadClientOpen, lifecycleFailureReason, lifecyclePinnedRpc, lifecycleRpc, lifecycleSourceClient, lifecycleStage, nitroArbSys, nitroArbSysAbi, nitroGasInfo, nitroGasInfoAbi, readLifecycleBlock, readLifecycleChainId, readNitroPosterGas, resolveLifecycleLimits, rpcHex, rpcObject, rpcQuantity, type LifecycleLimitObservation } from "./rpc.js";
4
+ import { assertLifecycleBlock, assertLifecycleReadClientOpen, lifecycleFailureReason, lifecyclePinnedRpc, lifecycleRpc, lifecycleSourceClient, lifecycleStage, nitroArbSys, nitroArbSysAbi, nitroGasInfo, nitroGasInfoAbi, readLifecycleBlock, readLifecycleChainId, readLifecycleGasPrice, readNitroPosterGas, registerLifecycleFinalCheck, resolveLifecycleLimits, rpcHex, rpcObject, rpcQuantity, type LifecycleLimitObservation } from "./rpc.js";
5
5
  import { LifecyclePlanningError, type ControlledLifecycleFork, type LifecycleBlock, type LifecycleLimitContext, type LifecyclePostcondition, type LifecycleRpcClient, type LifecycleSimulation, type LifecycleSimulationStep, type LifecycleTransaction, type PlannedLaunch, type ResolvedLifecycleLimits, type SimulateLaunchPlanOptions } from "./types.js";
6
6
  import { decodeAbyssLifecycleMarketConfig, decodePoolBoundV4LifecycleMarketConfig, decodeV4LifecycleMarketConfig, isPoolBoundV4ConfigVersion } from "./markets.js";
7
7
  import { hmmV2ForwardingReserve } from "./presets.js";
8
8
  import { transactionGasEstimate } from "./transactions.js";
9
+ import { hashUfgLaunchConfig } from "./ufg-config.js";
9
10
 
10
11
  function committedPositionCount(plan: LaunchPlanV1): number {
11
12
  let count = 0;
@@ -120,7 +121,7 @@ async function simulateRpcPass(client: LifecycleRpcClient, planned: PlannedLaunc
120
121
  // parent gasLimit are set.
121
122
  const blockStateCalls = transactions.map((transaction, index) => ({
122
123
  blockOverrides: { number: toHex(block.number + BigInt(index + 1)), time: toHex(block.timestamp + BigInt(index + 1)), gasLimit: toHex(block.gasLimit) },
123
- calls: [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gas: toHex(gasLimits[index] ?? limits.executionGasCeiling), gasPrice: toHex(gasPrice) }],
124
+ calls: [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gas: toHex(gasLimits[index] ?? limits.executionGasCeiling), gasPrice: toHex(gasPrice), ...(transaction.nonce === undefined ? {} : { nonce: toHex(transaction.nonce) }) }],
124
125
  }));
125
126
  const result = await lifecycleRpc(client, "eth_simulateV1", [{ blockStateCalls, validation, traceTransfers: false, returnFullTransactions: false }, toHex(block.number)]);
126
127
  if (!Array.isArray(result) || result.length !== transactions.length) throw new LifecyclePlanningError("INVALID_RPC_RESPONSE", "Sequential simulation omitted blocks");
@@ -163,7 +164,7 @@ async function simulateRpcPass(client: LifecycleRpcClient, planned: PlannedLaunc
163
164
  const buy = planned.plan.buys[buyIndex];
164
165
  if (buy === undefined || (receipt.quoteSpent[buyIndex] ?? buy.quoteAmountIn + 1n) > buy.quoteAmountIn || (receipt.tokenOut[buyIndex] ?? 0n) < buy.minTokenOut) throw new LifecyclePlanningError("POSTCONDITION_FAILED", "Simulation did not satisfy every ordered buy's budget and output minimum");
165
166
  }
166
- } else if (transaction.kind === "cancel" && !events.some((event) => event.eventName === "LaunchCancelled" && event.args.launchId.toLowerCase() === planned.launchId.toLowerCase() && event.args.creator.toLowerCase() === planned.account.toLowerCase())) throw new LifecyclePlanningError("POSTCONDITION_FAILED", "Simulation did not cancel the exact committed launch");
167
+ } else if (transaction.kind === "cancel" && !events.some((event) => event.eventName === "LaunchCancelled" && event.args.launchId.toLowerCase() === planned.launchId.toLowerCase() && event.args.creator.toLowerCase() === planned.plan.creator.toLowerCase())) throw new LifecyclePlanningError("POSTCONDITION_FAILED", "Simulation did not cancel the exact committed launch");
167
168
  else if ((transaction.kind === "approve" || transaction.kind === "approve-reset") && returnData !== "0x" && decodeFunctionResult({ abi: lifecycleErc20Abi, functionName: "approve", data: returnData }) !== true) throw new LifecyclePlanningError("POSTCONDITION_FAILED", "Funding approval returned failure");
168
169
  } catch (failure) { error = failure instanceof LifecyclePlanningError ? failure.message : "Simulation returned an invalid committed postcondition"; }
169
170
  }
@@ -233,12 +234,12 @@ async function simulateForkPass(fork: ControlledLifecycleFork, planned: PlannedL
233
234
  if (transaction === undefined || gas === undefined) throw new LifecyclePlanningError("INVALID_SIMULATION", "Missing fork transaction/gas context");
234
235
  try {
235
236
  if (measure) {
236
- const estimated = rpcQuantity(await lifecycleRpc(fork.client, "eth_estimateGas", [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gasPrice: toHex(gasPrice) }]), "fork sequential gas estimate");
237
+ const estimated = rpcQuantity(await lifecycleRpc(fork.client, "eth_estimateGas", [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gasPrice: toHex(gasPrice), ...(transaction.nonce === undefined ? {} : { nonce: toHex(transaction.nonce) }) }]), "fork sequential gas estimate");
237
238
  gasRequired = estimated;
238
239
  const buffered = (estimated * BigInt(10000 + headroomBps) + 9999n) / 10000n;
239
240
  if (buffered < gas) gas = buffered;
240
241
  }
241
- const hash = rpcHex(await lifecycleRpc(fork.client, "eth_sendTransaction", [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gas: toHex(gas), gasPrice: toHex(gasPrice) }]), "fork transaction hash");
242
+ const hash = rpcHex(await lifecycleRpc(fork.client, "eth_sendTransaction", [{ from: transaction.from, to: transaction.to, data: transaction.data, value: toHex(transaction.value), gas: toHex(gas), gasPrice: toHex(gasPrice), ...(transaction.nonce === undefined ? {} : { nonce: toHex(transaction.nonce) }) }]), "fork transaction hash");
242
243
  const receipt = await waitForkReceipt(fork.client, hash, fork.receiptTimeoutMs ?? 10_000);
243
244
  const gasUsed = rpcQuantity(receipt.gasUsed, "fork gas used");
244
245
  if (rpcQuantity(receipt.status, "fork transaction status") !== 1n) {
@@ -315,7 +316,7 @@ function observedFields<T extends object>(value: T): () => boolean {
315
316
 
316
317
  /** Internal continuation owned by one SDK read invocation. Only its positive
317
318
  * capability proof is reused; every candidate executes its entire economic sequence. */
318
- export function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, block: LifecycleBlock, hasTransactions = true, reviewedEnvelope?: NextTransactionEnvelope): PreparedLaunchSimulation {
319
+ export function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, block: LifecycleBlock, hasTransactions = true, reviewedEnvelope?: NextTransactionEnvelope, selectedGasPrice?: bigint): PreparedLaunchSimulation {
319
320
  const { client, planned, fork } = options;
320
321
  const signal = options.signal;
321
322
  if (signal?.aborted) throw Object.assign(new Error("Lifecycle simulation cancelled"), { name: "AbortError" });
@@ -346,6 +347,7 @@ export function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, bloc
346
347
  if (hashLaunchPlan(plan).toLowerCase() !== planHash.toLowerCase() || hashLaunchIdentity(plan).toLowerCase() !== launchId.toLowerCase()) {
347
348
  throw new LifecyclePlanningError("PLAN_MUTATED", "Economic plan changed after its simulation context was bound");
348
349
  }
350
+ if (planned.ufg !== undefined && hashUfgLaunchConfig(planned.ufg.config) !== planned.ufg.configHash) throw new LifecyclePlanningError("PLAN_MUTATED", "UFG treasury config changed after its simulation context was bound");
349
351
  };
350
352
  const pending = (async () => {
351
353
  if (fork !== undefined && lifecycleSourceClient(fork.client) === sourceClient) throw new LifecyclePlanningError("UNSAFE_FORK", "Source RPC must never receive controlled simulation transactions/snapshots/resets");
@@ -353,7 +355,7 @@ export function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, bloc
353
355
  resolveLifecycleLimits(context, policy),
354
356
  readLifecycleChainId(client),
355
357
  lifecyclePinnedRpc(client, "eth_getCode", [context.account, toHex(context.block.number)], context.block),
356
- hasTransactions && reviewedEnvelope === undefined ? lifecycleRpc(client, "eth_gasPrice") : undefined,
358
+ hasTransactions && reviewedEnvelope === undefined ? selectedGasPrice ?? readLifecycleGasPrice(client) : undefined,
357
359
  ]));
358
360
  })().then((observations) => ({ observations }), (failure: unknown) => ({ failure }));
359
361
  // Refused inputs may discard this read-only preparation before it settles.
@@ -417,8 +419,9 @@ export function prepareLaunchSimulation(options: SimulateLaunchPlanOptions, bloc
417
419
  await capabilityPending;
418
420
  assertCurrent();
419
421
  };
420
- const simulation = await simulateLaunchTransactionsWithContext(options, transactions, context, result.observations, proveBackend, assertCurrent, diagnostic, nextEnvelope);
422
+ const simulation = await simulateLaunchTransactionsWithContext(options, transactions, context, result.observations, proveBackend, assertCurrent, diagnostic, nextEnvelope, selectedGasPrice);
421
423
  assertCurrent();
424
+ registerLifecycleFinalCheck(client, result.observations[0].assertCurrent);
422
425
  return simulation;
423
426
  } catch (failure) {
424
427
  closed = true;
@@ -453,6 +456,7 @@ async function simulateLaunchTransactionsWithContext(
453
456
  assertCurrent: () => void,
454
457
  diagnostic: boolean,
455
458
  nextEnvelope?: NextTransactionEnvelope,
459
+ selectedGasPrice?: bigint,
456
460
  ): Promise<LifecycleSimulation> {
457
461
  const { client, planned } = options;
458
462
  const sourceClient = lifecycleSourceClient(client);
@@ -502,11 +506,11 @@ async function simulateLaunchTransactionsWithContext(
502
506
  return { ...base, confidence: "provisional", executionProof: "unavailable", backend: "unavailable", admitted: false, steps: [], failureCategory: "capacity", capacityConstraint: exceedsCompute ? "compute" : "simulation-gas", reason };
503
507
  }
504
508
  }
505
- const recommendedGasPrice = nextEnvelope === undefined ? rpcQuantity(gasPriceValue, "gas price") : nextEnvelope.gasPrice;
509
+ const recommendedGasPrice = nextEnvelope === undefined ? typeof gasPriceValue === "bigint" ? gasPriceValue : rpcQuantity(gasPriceValue, "gas price") : nextEnvelope.gasPrice;
506
510
  // New recommendations cover lagging quotes; reviewed fees are replayed unchanged
507
511
  // under natural child fees, never refreshed or silently increased.
508
512
  const baseFeeEnvelope = (block.baseFeePerGas ?? 0n) * 2n;
509
- const gasPrice = nextEnvelope?.gasPrice ?? (recommendedGasPrice > baseFeeEnvelope ? recommendedGasPrice : baseFeeEnvelope);
513
+ const gasPrice = nextEnvelope?.gasPrice ?? selectedGasPrice ?? (recommendedGasPrice > baseFeeEnvelope ? recommendedGasPrice : baseFeeEnvelope);
510
514
  if (gasPrice >= 1n << 256n) throw new LifecyclePlanningError("INVALID_RPC_RESPONSE", "Gas price must be a uint256 quantity");
511
515
  const buffer = (gas: bigint) => (gas * BigInt(10000 + limits.headroomBps) + 9999n) / 10000n;
512
516
  const posterGas: bigint[] = [];
@@ -1,4 +1,5 @@
1
1
  import type { Address, Hash, Hex } from "viem";
2
+ import type { UfgLaunchConfig } from "./ufg-config.js";
2
3
  import type {
3
4
  AdapterRegistrationV1, AssetFundingV1, LaunchExecutionMode, LaunchPlanV1, LaunchProgressV1,
4
5
  MarketLiveStateV1, PreparedMarketV1, ProfileRegistrationV1, ProfileTopologyV1, LaunchEnvelopeV2, LifecycleDeveloperTerms,
@@ -75,7 +76,7 @@ export type LifecyclePostcondition =
75
76
  export type LifecycleTransaction = {
76
77
  id: string; kind: LifecycleTransactionKind; chainId: number; from: Address; to: Address; data: Hex; value: bigint;
77
78
  dependencies: readonly string[]; postconditions: readonly LifecyclePostcondition[];
78
- marketStart?: number; marketCount?: number; gas?: bigint; gasPrice?: bigint;
79
+ marketStart?: number; marketCount?: number; gas?: bigint; gasPrice?: bigint; nonce?: bigint;
79
80
  /** Exact encoded byte count; populated on SDK-built commands, including approvals. */
80
81
  calldataBytes?: number;
81
82
  /** Exact current-state execution admission, not a wallet batch or future guarantee. */
@@ -161,6 +162,10 @@ export type PlannedLaunch = {
161
162
  plan: LaunchPlanV1; planHash: Hash; launchId: Hash; predictedToken: Address;
162
163
  tokenFactory: Address; tokenFactoryCodeHash: Hex;
163
164
  account: Address; chainId: bigint; mode: LaunchExecutionMode; confirmations: number;
165
+ /** Opt-in proxy routing; the committed creator remains the proxy, account is its principal. */
166
+ ufg?: { config: UfgLaunchConfig; configHash: Hash };
167
+ /** With admitted exact proof, transactions[0] is the immediate reviewed envelope,
168
+ * including nonce, gas and gasPrice. Deferred commands have no execution admission. */
164
169
  transactions: readonly LifecycleTransaction[]; prerequisites: readonly LifecycleFundingPrerequisite[];
165
170
  /** Sum of exact calldata bytes across the returned remaining commands, including approvals. */
166
171
  totalCalldataBytes: number;
@@ -176,16 +181,24 @@ export type PlanLaunchOptions = {
176
181
  client: LifecycleRpcClient; account: Address; plan: LaunchPlanV1; mode: LaunchExecutionMode;
177
182
  limits?: LifecycleLimitSource; fork?: ControlledLifecycleFork; receipts?: readonly LifecycleReceiptReference[];
178
183
  confirmations?: number; signal?: AbortSignal;
184
+ /** Opt in to the pinned UFG proxy; sender must match the nonce's principal namespace. */
185
+ ufg?: { config: UfgLaunchConfig };
179
186
  /** Unstarted only: permit interior gaps; opening containment, aligned ticks and the tail remain required. */
180
187
  allowTopologyGaps?: boolean;
181
188
  /** Unstarted only: waive the funded boundary tail; all other topology checks remain required. */
182
189
  allowMissingPermanentTail?: boolean;
183
190
  };
191
+ /** Explicit atomic final gas. Omitted price freezes this invocation's recommendation;
192
+ * a supplied price is replayed exactly, never refreshed or silently increased. */
193
+ export type LifecycleFinalEnvelope = Readonly<{ gas: bigint; gasPrice?: bigint }>;
184
194
  export type PrepareAndPlanLifecycleLaunchOptions = PlanLaunchOptions & {
185
195
  onProgress?: (progress: PoolBoundLifecyclePreparationProgress) => void;
186
196
  /** Protect every ordered buy from its actual diagnostic receipt output, rounded down.
187
197
  * Omitted preserves the caller's committed minima. Only an unstarted launch may be protected. */
188
198
  buySlippageBps?: number;
199
+ /** Atomic only, with no preceding approvals. Final calldata receives one exact
200
+ * validated replay, not a new gas recommendation or a larger rescue envelope. */
201
+ fixedFinalEnvelope?: LifecycleFinalEnvelope;
189
202
  };
190
203
  export type BuildLaunchTransactionsOptions = {
191
204
  plan: LaunchPlanV1; mode: LaunchExecutionMode;
@@ -201,7 +214,7 @@ export type SimulateLaunchPlanOptions = {
201
214
  signal?: AbortSignal;
202
215
  };
203
216
  export type ReadLaunchProgressOptions = {
204
- client: LifecycleRpcClient; planned: Pick<PlannedLaunch, "plan" | "planHash" | "launchId" | "predictedToken" | "account" | "mode" | "confirmations">;
217
+ client: LifecycleRpcClient; planned: Pick<PlannedLaunch, "plan" | "planHash" | "launchId" | "predictedToken" | "account" | "mode" | "confirmations" | "ufg">;
205
218
  receipts?: readonly LifecycleReceiptReference[]; confirmations?: number;
206
219
  signal?: AbortSignal;
207
220
  };
@@ -0,0 +1,173 @@
1
+ // Complete UFG ABIs; generated by scripts/generate-ufg-presets.mjs from protocol artifacts.
2
+ export const ufgLaunchProxyV1Abi = [
3
+ {"type":"constructor","inputs":[{"name":"orchestrator_","type":"address"},{"name":"registry_","type":"address"},{"name":"treasuryFactory_","type":"address"}],"stateMutability":"nonpayable"},
4
+ {"type":"receive","stateMutability":"payable"},
5
+ {"type":"function","name":"activateLaunch","inputs":[{"name":"plan","type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"orchestrator","type":"address"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"token","type":"tuple","components":[{"name":"kind","type":"uint8"},{"name":"rewardMode","type":"uint8"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"supply","type":"uint256"},{"name":"nftUnit","type":"uint256"},{"name":"metadataURI","type":"string"},{"name":"salt","type":"bytes32"},{"name":"inventoryRecipient","type":"address"},{"name":"burnOnCancel","type":"bool"}]},{"name":"funding","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"amount","type":"uint256"},{"name":"kind","type":"uint8"},{"name":"inputAsset","type":"address"},{"name":"inputAmount","type":"uint256"},{"name":"target","type":"address"},{"name":"data","type":"bytes"}]},{"name":"feeAssets","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"ownerBps","type":"uint16"},{"name":"rewardsBps","type":"uint16"},{"name":"burnBps","type":"uint16"}]},{"name":"markets","type":"tuple[]","components":[{"name":"adapterId","type":"bytes32"},{"name":"profileId","type":"bytes32"},{"name":"quoteAsset","type":"address"},{"name":"tokenBudget","type":"uint256"},{"name":"configVersion","type":"uint32"},{"name":"config","type":"bytes"}]},{"name":"buys","type":"tuple[]","components":[{"name":"marketIndex","type":"uint32"},{"name":"quoteAmountIn","type":"uint256"},{"name":"minTokenOut","type":"uint256"},{"name":"recipient","type":"address"},{"name":"sqrtPriceLimitX96","type":"uint160"}]},{"name":"deadline","type":"uint256"},{"name":"executorFeeBps","type":"uint16"}]}],"outputs":[{"name":"receipt","type":"tuple","components":[{"name":"launchId","type":"bytes32"},{"name":"planHash","type":"bytes32"},{"name":"token","type":"address"},{"name":"feeHub","type":"address"},{"name":"rewards","type":"address"},{"name":"marketCount","type":"uint32"},{"name":"positionCount","type":"uint32"},{"name":"quoteSpent","type":"uint256[]"},{"name":"tokenOut","type":"uint256[]"}]}],"stateMutability":"nonpayable"},
6
+ {"type":"function","name":"beginLaunch","inputs":[{"name":"plan","type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"orchestrator","type":"address"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"token","type":"tuple","components":[{"name":"kind","type":"uint8"},{"name":"rewardMode","type":"uint8"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"supply","type":"uint256"},{"name":"nftUnit","type":"uint256"},{"name":"metadataURI","type":"string"},{"name":"salt","type":"bytes32"},{"name":"inventoryRecipient","type":"address"},{"name":"burnOnCancel","type":"bool"}]},{"name":"funding","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"amount","type":"uint256"},{"name":"kind","type":"uint8"},{"name":"inputAsset","type":"address"},{"name":"inputAmount","type":"uint256"},{"name":"target","type":"address"},{"name":"data","type":"bytes"}]},{"name":"feeAssets","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"ownerBps","type":"uint16"},{"name":"rewardsBps","type":"uint16"},{"name":"burnBps","type":"uint16"}]},{"name":"markets","type":"tuple[]","components":[{"name":"adapterId","type":"bytes32"},{"name":"profileId","type":"bytes32"},{"name":"quoteAsset","type":"address"},{"name":"tokenBudget","type":"uint256"},{"name":"configVersion","type":"uint32"},{"name":"config","type":"bytes"}]},{"name":"buys","type":"tuple[]","components":[{"name":"marketIndex","type":"uint32"},{"name":"quoteAmountIn","type":"uint256"},{"name":"minTokenOut","type":"uint256"},{"name":"recipient","type":"address"},{"name":"sqrtPriceLimitX96","type":"uint160"}]},{"name":"deadline","type":"uint256"},{"name":"executorFeeBps","type":"uint16"}]},{"name":"mode","type":"uint8"},{"name":"config","type":"tuple","components":[{"name":"treasuryShareBps","type":"uint16"},{"name":"exitFeeBps","type":"uint16"},{"name":"reserveAssets","type":"address[]"}]}],"outputs":[{"name":"progress","type":"tuple","components":[{"name":"launchId","type":"bytes32"},{"name":"planHash","type":"bytes32"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"mode","type":"uint8"},{"name":"phase","type":"uint8"},{"name":"token","type":"address"},{"name":"feeHub","type":"address"},{"name":"rewards","type":"address"},{"name":"preparedMarkets","type":"uint32"},{"name":"marketCount","type":"uint32"},{"name":"buyCount","type":"uint32"},{"name":"positionCount","type":"uint32"},{"name":"deadline","type":"uint256"}]}],"stateMutability":"payable"},
7
+ {"type":"function","name":"cancelLaunch","inputs":[{"name":"plan","type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"orchestrator","type":"address"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"token","type":"tuple","components":[{"name":"kind","type":"uint8"},{"name":"rewardMode","type":"uint8"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"supply","type":"uint256"},{"name":"nftUnit","type":"uint256"},{"name":"metadataURI","type":"string"},{"name":"salt","type":"bytes32"},{"name":"inventoryRecipient","type":"address"},{"name":"burnOnCancel","type":"bool"}]},{"name":"funding","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"amount","type":"uint256"},{"name":"kind","type":"uint8"},{"name":"inputAsset","type":"address"},{"name":"inputAmount","type":"uint256"},{"name":"target","type":"address"},{"name":"data","type":"bytes"}]},{"name":"feeAssets","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"ownerBps","type":"uint16"},{"name":"rewardsBps","type":"uint16"},{"name":"burnBps","type":"uint16"}]},{"name":"markets","type":"tuple[]","components":[{"name":"adapterId","type":"bytes32"},{"name":"profileId","type":"bytes32"},{"name":"quoteAsset","type":"address"},{"name":"tokenBudget","type":"uint256"},{"name":"configVersion","type":"uint32"},{"name":"config","type":"bytes"}]},{"name":"buys","type":"tuple[]","components":[{"name":"marketIndex","type":"uint32"},{"name":"quoteAmountIn","type":"uint256"},{"name":"minTokenOut","type":"uint256"},{"name":"recipient","type":"address"},{"name":"sqrtPriceLimitX96","type":"uint160"}]},{"name":"deadline","type":"uint256"},{"name":"executorFeeBps","type":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},
8
+ {"type":"function","name":"feeOwnerRegistry","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
9
+ {"type":"function","name":"handoffFeeOwnership","inputs":[{"name":"token","type":"address"},{"name":"adapter","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
10
+ {"type":"function","name":"launchAtomic","inputs":[{"name":"plan","type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"orchestrator","type":"address"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"token","type":"tuple","components":[{"name":"kind","type":"uint8"},{"name":"rewardMode","type":"uint8"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"supply","type":"uint256"},{"name":"nftUnit","type":"uint256"},{"name":"metadataURI","type":"string"},{"name":"salt","type":"bytes32"},{"name":"inventoryRecipient","type":"address"},{"name":"burnOnCancel","type":"bool"}]},{"name":"funding","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"amount","type":"uint256"},{"name":"kind","type":"uint8"},{"name":"inputAsset","type":"address"},{"name":"inputAmount","type":"uint256"},{"name":"target","type":"address"},{"name":"data","type":"bytes"}]},{"name":"feeAssets","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"ownerBps","type":"uint16"},{"name":"rewardsBps","type":"uint16"},{"name":"burnBps","type":"uint16"}]},{"name":"markets","type":"tuple[]","components":[{"name":"adapterId","type":"bytes32"},{"name":"profileId","type":"bytes32"},{"name":"quoteAsset","type":"address"},{"name":"tokenBudget","type":"uint256"},{"name":"configVersion","type":"uint32"},{"name":"config","type":"bytes"}]},{"name":"buys","type":"tuple[]","components":[{"name":"marketIndex","type":"uint32"},{"name":"quoteAmountIn","type":"uint256"},{"name":"minTokenOut","type":"uint256"},{"name":"recipient","type":"address"},{"name":"sqrtPriceLimitX96","type":"uint160"}]},{"name":"deadline","type":"uint256"},{"name":"executorFeeBps","type":"uint16"}]},{"name":"config","type":"tuple","components":[{"name":"treasuryShareBps","type":"uint16"},{"name":"exitFeeBps","type":"uint16"},{"name":"reserveAssets","type":"address[]"}]}],"outputs":[{"name":"receipt","type":"tuple","components":[{"name":"launchId","type":"bytes32"},{"name":"planHash","type":"bytes32"},{"name":"token","type":"address"},{"name":"feeHub","type":"address"},{"name":"rewards","type":"address"},{"name":"marketCount","type":"uint32"},{"name":"positionCount","type":"uint32"},{"name":"quoteSpent","type":"uint256[]"},{"name":"tokenOut","type":"uint256[]"}]}],"stateMutability":"payable"},
11
+ {"type":"function","name":"launchConfigHash","inputs":[{"name":"launchId","type":"bytes32"}],"outputs":[{"name":"configHash","type":"bytes32"}],"stateMutability":"view"},
12
+ {"type":"function","name":"nonceOf","inputs":[{"name":"principal","type":"address"},{"name":"nonce","type":"uint96"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"pure"},
13
+ {"type":"function","name":"orchestrator","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
14
+ {"type":"function","name":"prepareMarkets","inputs":[{"name":"plan","type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"orchestrator","type":"address"},{"name":"creator","type":"address"},{"name":"nonce","type":"uint256"},{"name":"token","type":"tuple","components":[{"name":"kind","type":"uint8"},{"name":"rewardMode","type":"uint8"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"supply","type":"uint256"},{"name":"nftUnit","type":"uint256"},{"name":"metadataURI","type":"string"},{"name":"salt","type":"bytes32"},{"name":"inventoryRecipient","type":"address"},{"name":"burnOnCancel","type":"bool"}]},{"name":"funding","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"amount","type":"uint256"},{"name":"kind","type":"uint8"},{"name":"inputAsset","type":"address"},{"name":"inputAmount","type":"uint256"},{"name":"target","type":"address"},{"name":"data","type":"bytes"}]},{"name":"feeAssets","type":"tuple[]","components":[{"name":"asset","type":"address"},{"name":"ownerBps","type":"uint16"},{"name":"rewardsBps","type":"uint16"},{"name":"burnBps","type":"uint16"}]},{"name":"markets","type":"tuple[]","components":[{"name":"adapterId","type":"bytes32"},{"name":"profileId","type":"bytes32"},{"name":"quoteAsset","type":"address"},{"name":"tokenBudget","type":"uint256"},{"name":"configVersion","type":"uint32"},{"name":"config","type":"bytes"}]},{"name":"buys","type":"tuple[]","components":[{"name":"marketIndex","type":"uint32"},{"name":"quoteAmountIn","type":"uint256"},{"name":"minTokenOut","type":"uint256"},{"name":"recipient","type":"address"},{"name":"sqrtPriceLimitX96","type":"uint160"}]},{"name":"deadline","type":"uint256"},{"name":"executorFeeBps","type":"uint16"}]},{"name":"firstMarket","type":"uint32"},{"name":"count","type":"uint32"}],"outputs":[],"stateMutability":"nonpayable"},
15
+ {"type":"function","name":"principalOf","inputs":[{"name":"launchId","type":"bytes32"}],"outputs":[{"name":"principal","type":"address"}],"stateMutability":"view"},
16
+ {"type":"function","name":"treasuryFactory","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
17
+ {"type":"event","name":"LaunchConfigBound","inputs":[{"name":"launchId","type":"bytes32","indexed":true},{"name":"planHash","type":"bytes32","indexed":false},{"name":"configHash","type":"bytes32","indexed":false}],"anonymous":false},
18
+ {"type":"error","name":"InexactTransfer","inputs":[]},
19
+ {"type":"error","name":"InvalidConfiguration","inputs":[]},
20
+ {"type":"error","name":"InvalidNonce","inputs":[]},
21
+ {"type":"error","name":"InvalidPlan","inputs":[]},
22
+ {"type":"error","name":"PlanMismatch","inputs":[]},
23
+ {"type":"error","name":"Reentrancy","inputs":[]},
24
+ {"type":"error","name":"TooManyReserves","inputs":[]},
25
+ {"type":"error","name":"Unauthorized","inputs":[]},
26
+ ] as const;
27
+
28
+ export const ufgTreasuryFactoryV1Abi = [
29
+ {"type":"constructor","inputs":[{"name":"hubFactory_","type":"address"},{"name":"approvedProxy_","type":"address"},{"name":"collectorDeployer_","type":"address"},{"name":"splitter_","type":"address"},{"name":"platformShareBps_","type":"uint16"},{"name":"ratePerSecond_","type":"uint256"},{"name":"upstreamFactory_","type":"address"},{"name":"upstreamFactoryCodeHash_","type":"bytes32"}],"stateMutability":"nonpayable"},
30
+ {"type":"function","name":"MAX_INIT_CODE_SIZE","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
31
+ {"type":"function","name":"MAX_PLATFORM_SHARE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
32
+ {"type":"function","name":"MAX_RUNTIME_SIZE","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
33
+ {"type":"function","name":"approvedProxy","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
34
+ {"type":"function","name":"approvedProxyCodeHash","inputs":[],"outputs":[{"name":"","type":"bytes32"}],"stateMutability":"view"},
35
+ {"type":"function","name":"collectorDeployer","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
36
+ {"type":"function","name":"configHash","inputs":[{"name":"token","type":"address"}],"outputs":[{"name":"hash","type":"bytes32"}],"stateMutability":"view"},
37
+ {"type":"function","name":"decodeLaunchConfig","inputs":[{"name":"encoded","type":"bytes"},{"name":"canonicalPrefix","type":"bytes"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"treasuryShareBps","type":"uint16"},{"name":"exitFeeBps","type":"uint16"},{"name":"reserveAssets","type":"address[]"}]}],"stateMutability":"pure"},
38
+ {"type":"function","name":"deployedCodeHash","inputs":[{"name":"deployed","type":"address"}],"outputs":[{"name":"hash","type":"bytes32"}],"stateMutability":"view"},
39
+ {"type":"function","name":"feeOwnerRegistry","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
40
+ {"type":"function","name":"fundingAdapterOf","inputs":[{"name":"token","type":"address"}],"outputs":[{"name":"adapter","type":"address"}],"stateMutability":"view"},
41
+ {"type":"function","name":"getOrCreate","inputs":[{"name":"token","type":"address"},{"name":"hub","type":"address"},{"name":"config","type":"tuple","components":[{"name":"treasuryShareBps","type":"uint16"},{"name":"exitFeeBps","type":"uint16"},{"name":"reserveAssets","type":"address[]"}]},{"name":"feeMode","type":"uint8"},{"name":"lpFeePips","type":"uint24"}],"outputs":[{"name":"adapter","type":"address"},{"name":"treasury","type":"address"}],"stateMutability":"nonpayable"},
42
+ {"type":"function","name":"hubFactory","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
43
+ {"type":"function","name":"platformShareBps","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
44
+ {"type":"function","name":"ratePerSecond","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
45
+ {"type":"function","name":"splitter","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
46
+ {"type":"function","name":"treasuryOf","inputs":[{"name":"token","type":"address"}],"outputs":[{"name":"treasury","type":"address"}],"stateMutability":"view"},
47
+ {"type":"function","name":"upstreamFactory","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
48
+ {"type":"function","name":"upstreamFactoryCodeHash","inputs":[],"outputs":[{"name":"","type":"bytes32"}],"stateMutability":"view"},
49
+ {"type":"function","name":"validateMarketLaunchConfig","inputs":[{"name":"encoded","type":"bytes"},{"name":"canonicalPrefix","type":"bytes"},{"name":"token","type":"address"},{"name":"quote","type":"address"}],"outputs":[{"name":"launch","type":"tuple","components":[{"name":"treasuryShareBps","type":"uint16"},{"name":"exitFeeBps","type":"uint16"},{"name":"reserveAssets","type":"address[]"}]}],"stateMutability":"view"},
50
+ {"type":"event","name":"TreasuryCreated","inputs":[{"name":"token","type":"address","indexed":true},{"name":"hub","type":"address","indexed":true},{"name":"treasury","type":"address","indexed":true},{"name":"fundingAdapter","type":"address","indexed":false},{"name":"configHash","type":"bytes32","indexed":false}],"anonymous":false},
51
+ {"type":"error","name":"DeploymentFailed","inputs":[]},
52
+ {"type":"error","name":"InconsistentConfiguration","inputs":[]},
53
+ {"type":"error","name":"InitCodeTooLarge","inputs":[]},
54
+ {"type":"error","name":"InvalidConfiguration","inputs":[]},
55
+ {"type":"error","name":"InvalidHub","inputs":[]},
56
+ {"type":"error","name":"InvalidUFGConfiguration","inputs":[]},
57
+ {"type":"error","name":"Reentrancy","inputs":[]},
58
+ {"type":"error","name":"RuntimeCodeTooLarge","inputs":[]},
59
+ {"type":"error","name":"Unauthorized","inputs":[]},
60
+ {"type":"error","name":"UnlockedLaunch","inputs":[]},
61
+ ] as const;
62
+
63
+ export const ufgBlackMarketFactoryAbi = [
64
+ {"type":"constructor","inputs":[{"name":"tokenFactory_","type":"address"},{"name":"hubFactory_","type":"address"},{"name":"splitter_","type":"address"},{"name":"platformShareBps_","type":"uint16"},{"name":"ratePerSecond_","type":"uint256"}],"stateMutability":"nonpayable"},
65
+ {"type":"function","name":"ABYSS_HUB_FACTORY","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
66
+ {"type":"function","name":"ABYSS_TOKEN_FACTORY","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
67
+ {"type":"function","name":"MAX_EXIT_FEE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
68
+ {"type":"function","name":"MAX_PLATFORM_SHARE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
69
+ {"type":"function","name":"MAX_RATE_PER_SECOND","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
70
+ {"type":"function","name":"PLATFORM_SHARE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
71
+ {"type":"function","name":"RATE_PER_SECOND","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
72
+ {"type":"function","name":"SPLITTER","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
73
+ {"type":"function","name":"deploy","inputs":[{"name":"token","type":"address"},{"name":"canonicalHub","type":"address"},{"name":"fundingAdapter","type":"address"},{"name":"rewardAssets","type":"address[]"},{"name":"exitFeeBps","type":"uint16"}],"outputs":[{"name":"treasury","type":"address"}],"stateMutability":"nonpayable"},
74
+ {"type":"function","name":"launchCount","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
75
+ {"type":"function","name":"predict","inputs":[{"name":"token","type":"address"},{"name":"canonicalHub","type":"address"},{"name":"fundingAdapter","type":"address"},{"name":"rewardAssets","type":"address[]"},{"name":"exitFeeBps","type":"uint16"}],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
76
+ {"type":"function","name":"treasuries","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
77
+ {"type":"event","name":"FundingAdapterBound","inputs":[{"name":"token","type":"address","indexed":true},{"name":"canonicalHub","type":"address","indexed":true},{"name":"fundingAdapter","type":"address","indexed":true},{"name":"treasury","type":"address","indexed":false}],"anonymous":false},
78
+ {"type":"event","name":"TreasuryDeployed","inputs":[{"name":"token","type":"address","indexed":true},{"name":"hub","type":"address","indexed":true},{"name":"treasury","type":"address","indexed":true},{"name":"rewardAssets","type":"address[]","indexed":false},{"name":"exitFeeBps","type":"uint16","indexed":false}],"anonymous":false},
79
+ {"type":"error","name":"AlreadyDeployed","inputs":[]},
80
+ {"type":"error","name":"BadConfiguration","inputs":[]},
81
+ {"type":"error","name":"BadExitFee","inputs":[]},
82
+ {"type":"error","name":"BadFundingAdapter","inputs":[]},
83
+ {"type":"error","name":"BountyNotZero","inputs":[]},
84
+ {"type":"error","name":"HubTokenMismatch","inputs":[]},
85
+ {"type":"error","name":"NotTokenFactory","inputs":[]},
86
+ {"type":"error","name":"UnknownHub","inputs":[]},
87
+ ] as const;
88
+
89
+ export const ufgBlackMarketTreasuryAbi = [
90
+ {"type":"constructor","inputs":[{"name":"token","type":"address"},{"name":"hub","type":"address"},{"name":"assets_","type":"address[]"},{"name":"exitFeeBps","type":"uint16"},{"name":"splitter","type":"address"},{"name":"platformShareBps","type":"uint16"},{"name":"ratePerSecond","type":"uint256"}],"stateMutability":"nonpayable"},
91
+ {"type":"function","name":"DEAD","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
92
+ {"type":"function","name":"EXIT_FEE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
93
+ {"type":"function","name":"HUB","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
94
+ {"type":"function","name":"LIQUIDATION_LTV_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
95
+ {"type":"function","name":"LTV_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
96
+ {"type":"function","name":"MAX_ASSETS","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
97
+ {"type":"function","name":"MAX_EXIT_FEE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
98
+ {"type":"function","name":"MAX_INDEX","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
99
+ {"type":"function","name":"MAX_RATE_PER_SECOND","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
100
+ {"type":"function","name":"MIN_DEBT","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
101
+ {"type":"function","name":"PLATFORM_SHARE_BPS","inputs":[],"outputs":[{"name":"","type":"uint16"}],"stateMutability":"view"},
102
+ {"type":"function","name":"RATE_PER_SECOND","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
103
+ {"type":"function","name":"SPLITTER","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
104
+ {"type":"function","name":"TOKEN","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
105
+ {"type":"function","name":"addCollateral","inputs":[{"name":"amount","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
106
+ {"type":"function","name":"annualRate","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
107
+ {"type":"function","name":"assets","inputs":[],"outputs":[{"name":"","type":"address[]"}],"stateMutability":"view"},
108
+ {"type":"function","name":"backing","inputs":[{"name":"asset","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
109
+ {"type":"function","name":"borrow","inputs":[{"name":"amounts","type":"uint256[]"},{"name":"to","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
110
+ {"type":"function","name":"burnStray","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
111
+ {"type":"function","name":"collect","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
112
+ {"type":"function","name":"debtOf","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"out","type":"uint256[]"}],"stateMutability":"view"},
113
+ {"type":"function","name":"distributor","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
114
+ {"type":"function","name":"effectiveSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
115
+ {"type":"function","name":"interestIndex","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
116
+ {"type":"function","name":"isLiquidatable","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"bool"}],"stateMutability":"view"},
117
+ {"type":"function","name":"lastAccrual","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
118
+ {"type":"function","name":"liquid","inputs":[{"name":"asset","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
119
+ {"type":"function","name":"liquidate","inputs":[{"name":"account","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
120
+ {"type":"function","name":"maxBorrow","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"out","type":"uint256[]"}],"stateMutability":"view"},
121
+ {"type":"function","name":"notifyRewardAmounts","inputs":[{"name":"amounts","type":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},
122
+ {"type":"function","name":"originationCap","inputs":[{"name":"collateral","type":"uint256"}],"outputs":[{"name":"out","type":"uint256[]"}],"stateMutability":"view"},
123
+ {"type":"function","name":"owed","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
124
+ {"type":"function","name":"positionOf","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"collateral","type":"uint256"},{"name":"principal","type":"uint256[]"},{"name":"debt","type":"uint256[]"}],"stateMutability":"view"},
125
+ {"type":"function","name":"principalOutstanding","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
126
+ {"type":"function","name":"quoteRedeem","inputs":[{"name":"amount","type":"uint256"}],"outputs":[{"name":"out","type":"uint256[]"}],"stateMutability":"view"},
127
+ {"type":"function","name":"redeem","inputs":[{"name":"amount","type":"uint256"},{"name":"minOuts","type":"uint256[]"},{"name":"to","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
128
+ {"type":"function","name":"redeemSkipping","inputs":[{"name":"amount","type":"uint256"},{"name":"minOuts","type":"uint256[]"},{"name":"to","type":"address"},{"name":"skipMask","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
129
+ {"type":"function","name":"releasePlatformFees","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
130
+ {"type":"function","name":"releasePlatformFeesFor","inputs":[{"name":"assets_","type":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},
131
+ {"type":"function","name":"repay","inputs":[{"name":"account","type":"address"},{"name":"amounts","type":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},
132
+ {"type":"function","name":"reserve","inputs":[{"name":"asset","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
133
+ {"type":"function","name":"rewardAssets","inputs":[],"outputs":[{"name":"","type":"address[]"}],"stateMutability":"view"},
134
+ {"type":"function","name":"rewardAvailableBalance","inputs":[{"name":"asset","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
135
+ {"type":"function","name":"totalCollateral","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
136
+ {"type":"function","name":"withdrawCollateral","inputs":[{"name":"amount","type":"uint256"},{"name":"to","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
137
+ {"type":"event","name":"AssetsSkipped","inputs":[{"name":"caller","type":"address","indexed":true},{"name":"skipMask","type":"uint256","indexed":false}],"anonymous":false},
138
+ {"type":"event","name":"CollateralAdded","inputs":[{"name":"account","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false},
139
+ {"type":"event","name":"CollateralWithdrawn","inputs":[{"name":"account","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false},
140
+ {"type":"event","name":"CollectFailed","inputs":[{"name":"reason","type":"bytes","indexed":false}],"anonymous":false},
141
+ {"type":"event","name":"Funded","inputs":[{"name":"asset","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"platformPart","type":"uint256","indexed":false}],"anonymous":false},
142
+ {"type":"event","name":"PlatformFeesReleased","inputs":[{"name":"asset","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false},
143
+ {"type":"event","name":"Redeemed","inputs":[{"name":"caller","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"burned","type":"uint256","indexed":false},{"name":"paid","type":"uint256[]","indexed":false},{"name":"fee","type":"uint256[]","indexed":false}],"anonymous":false},
144
+ {"type":"event","name":"ReserveLoanBorrowed","inputs":[{"name":"account","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"asset","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false},
145
+ {"type":"event","name":"ReserveLoanLiquidated","inputs":[{"name":"account","type":"address","indexed":true},{"name":"caller","type":"address","indexed":true},{"name":"burned","type":"uint256","indexed":false},{"name":"assets","type":"address[]","indexed":false},{"name":"principals","type":"uint256[]","indexed":false}],"anonymous":false},
146
+ {"type":"event","name":"ReserveLoanRepaid","inputs":[{"name":"account","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"asset","type":"address","indexed":true},{"name":"principal","type":"uint256","indexed":false},{"name":"interest","type":"uint256","indexed":false}],"anonymous":false},
147
+ {"type":"event","name":"StrayBurned","inputs":[{"name":"amount","type":"uint256","indexed":false}],"anonymous":false},
148
+ {"type":"error","name":"BadAmounts","inputs":[]},
149
+ {"type":"error","name":"BadAssets","inputs":[]},
150
+ {"type":"error","name":"BadExitFee","inputs":[]},
151
+ {"type":"error","name":"BadHub","inputs":[]},
152
+ {"type":"error","name":"BadRate","inputs":[]},
153
+ {"type":"error","name":"BadRecipient","inputs":[]},
154
+ {"type":"error","name":"BadShare","inputs":[]},
155
+ {"type":"error","name":"BadSkipMask","inputs":[]},
156
+ {"type":"error","name":"BadSplitter","inputs":[]},
157
+ {"type":"error","name":"BadToken","inputs":[]},
158
+ {"type":"error","name":"BelowMinDebt","inputs":[]},
159
+ {"type":"error","name":"ExceedsCap","inputs":[]},
160
+ {"type":"error","name":"IndexSaturated","inputs":[]},
161
+ {"type":"error","name":"InsufficientCollateral","inputs":[]},
162
+ {"type":"error","name":"InsufficientLiquidity","inputs":[]},
163
+ {"type":"error","name":"NoPosition","inputs":[]},
164
+ {"type":"error","name":"NotHub","inputs":[]},
165
+ {"type":"error","name":"NotLiquidatable","inputs":[]},
166
+ {"type":"error","name":"NothingToRepay","inputs":[]},
167
+ {"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},
168
+ {"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address"}]},
169
+ {"type":"error","name":"SlippageExceeded","inputs":[]},
170
+ {"type":"error","name":"ZeroAmount","inputs":[]},
171
+ {"type":"error","name":"ZeroPayout","inputs":[]},
172
+ {"type":"error","name":"ZeroSupply","inputs":[]},
173
+ ] as const;
@@ -0,0 +1,77 @@
1
+ import { decodeAbiParameters, encodeAbiParameters, getAddress, keccak256, type Address, type Hex } from "viem";
2
+ import type { LaunchPlanV1, LifecycleFeeAssetPolicyV2 } from "./schema.js";
3
+ import { LifecyclePlanningError } from "./types.js";
4
+
5
+ export const UFG_LAUNCH_PROXY_ADDRESS: Address = "0xf6673d859DE03eB74A0b01696Edb97f941dFD0CA";
6
+ export const UFG_TREASURY_FACTORY_ADDRESS: Address = "0x26Aa5D52134c8E6c4C01E9fb53A7568c0C64901F";
7
+ export const UFG_UPSTREAM_FACTORY_ADDRESS: Address = "0xA170b5A58C111334A7237F2Ea2c428ec5022f68E";
8
+ export const UFG_ORCHESTRATOR_ADDRESS: Address = "0x91560876033d568d25CDe98C78c33ff8FC43962c";
9
+ export const UFG_FIXED_PROFILE_ID: Hex = "0x5c6045af480814e469f3dba7c120d264047c9320b869c63a064536041a2dbae6";
10
+ export const UFG_DYNAMIC_PROFILE_ID: Hex = "0x03de8d5e38f2957d80ecb9f2e59d555601ff091dfb17bce84178956a2e8d9b41";
11
+ export const UFG_FIXED_ADAPTER_ID: Hex = "0x073a4d46af70a3d4f69641e4f9dcdc9d8c279cd443daff960bbdf65a3b5fc758";
12
+ export const UFG_DYNAMIC_ADAPTER_ID: Hex = "0xc0906e17625b48240a87a3afc6ee921b653bdacd72906a16b359d0776d938518";
13
+
14
+ export function isUfgProfile(profileId: Hex): boolean {
15
+ const id = profileId.toLowerCase();
16
+ return id === UFG_FIXED_PROFILE_ID || id === UFG_DYNAMIC_PROFILE_ID;
17
+ }
18
+
19
+ export type UfgLaunchConfig = { treasuryShareBps: number; exitFeeBps: number; reserveAssets: readonly Address[] };
20
+ export const ufgLaunchConfigComponents = [
21
+ { name: "treasuryShareBps", type: "uint16" }, { name: "exitFeeBps", type: "uint16" },
22
+ { name: "reserveAssets", type: "address[]" },
23
+ ] as const;
24
+
25
+ /** The proxy has seven reserve slots; its eighth fee asset is the launched token. */
26
+ export function validateUfgLaunchConfig(config: UfgLaunchConfig): void {
27
+ if (config.treasuryShareBps !== 10000 || !Number.isInteger(config.exitFeeBps) || config.exitFeeBps < 0 || config.exitFeeBps > 2000 || config.reserveAssets.length < 1 || config.reserveAssets.length > 7) {
28
+ throw new LifecyclePlanningError("INVALID_UFG_CONFIG", "UFG requires 10000 treasury bps, exit fee 0..2000 bps and one to seven reserves");
29
+ }
30
+ let previous = 0n;
31
+ for (const asset of config.reserveAssets) {
32
+ getAddress(asset);
33
+ if (BigInt(asset) <= previous) throw new LifecyclePlanningError("INVALID_UFG_CONFIG", "UFG reserves must be nonzero, unique and strictly ascending");
34
+ previous = BigInt(asset);
35
+ }
36
+ }
37
+
38
+ /** abi.encode(UFGLaunchConfigV1): one dynamic tuple, including its leading 0x20 offset. */
39
+ export function encodeUfgLaunchConfig(config: UfgLaunchConfig): Hex {
40
+ validateUfgLaunchConfig(config);
41
+ return encodeAbiParameters([{ type: "tuple", components: ufgLaunchConfigComponents }], [config]);
42
+ }
43
+ export function decodeUfgLaunchConfig(encoded: Hex): UfgLaunchConfig {
44
+ const config = decodeAbiParameters([{ type: "tuple", components: ufgLaunchConfigComponents }], encoded)[0];
45
+ if (encodeUfgLaunchConfig(config).toLowerCase() !== encoded.toLowerCase()) throw new LifecyclePlanningError("INVALID_UFG_CONFIG", "UFG launch config must use canonical tuple encoding with no extra bytes");
46
+ return config;
47
+ }
48
+ export function hashUfgLaunchConfig(config: UfgLaunchConfig): Hex {
49
+ return keccak256(encodeUfgLaunchConfig(config));
50
+ }
51
+ export function ufgLaunchNonce(principal: Address, nonce: bigint): bigint {
52
+ getAddress(principal);
53
+ if (BigInt(principal) === 0n || nonce < 0n || nonce >= 1n << 96n) throw new LifecyclePlanningError("INVALID_UFG_NONCE", "UFG requires a nonzero principal and a uint96 nonce");
54
+ return BigInt(principal) << 96n | nonce;
55
+ }
56
+
57
+ /** Internal routing guard, also used by canonical progress and receipt verification. */
58
+ export function assertUfgLaunchAccount(plan: LaunchPlanV1, account: Address): void {
59
+ if (plan.chainId !== 4663n || plan.orchestrator.toLowerCase() !== UFG_ORCHESTRATOR_ADDRESS.toLowerCase() || plan.creator.toLowerCase() !== UFG_LAUNCH_PROXY_ADDRESS.toLowerCase() || plan.nonce < 0n || plan.nonce >= 1n << 256n || plan.nonce >> 96n !== BigInt(account) || BigInt(account) === 0n) {
60
+ throw new LifecyclePlanningError("INVALID_UFG_PLAN", "UFG plans require the pinned Robinhood core/proxy and the sender's principal-namespaced nonce");
61
+ }
62
+ }
63
+ export function ufgPlanPrincipal(plan: LaunchPlanV1): Address {
64
+ if (plan.nonce < 0n || plan.nonce >= 1n << 256n) throw new LifecyclePlanningError("INVALID_UFG_PLAN", "UFG nonce must fit uint256");
65
+ const principal = getAddress(`0x${(plan.nonce >> 96n).toString(16).padStart(40, "0")}`);
66
+ assertUfgLaunchAccount(plan, principal);
67
+ return principal;
68
+ }
69
+ export function buildUfgFeeAssetPolicies(token: Address, reserveAssets: readonly Address[]): LifecycleFeeAssetPolicyV2[] {
70
+ validateUfgLaunchConfig({ treasuryShareBps: 10000, exitFeeBps: 0, reserveAssets });
71
+ getAddress(token);
72
+ if (BigInt(token) === 0n || reserveAssets.some((asset) => asset.toLowerCase() === token.toLowerCase())) throw new LifecyclePlanningError("INVALID_UFG_CONFIG", "The launched token must be nonzero and distinct from every reserve");
73
+ return [
74
+ { asset: token, ownerBps: 0, rewardsBps: 0, burnBps: 10000 },
75
+ ...reserveAssets.map((asset) => ({ asset, ownerBps: 10000, rewardsBps: 0, burnBps: 0 })),
76
+ ].sort((a, b) => BigInt(a.asset) < BigInt(b.asset) ? -1 : 1);
77
+ }