@black-market/sdk 0.10.0 → 0.12.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 (83) hide show
  1. package/README.md +21 -2
  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/calibration.d.ts.map +1 -1
  7. package/dist/lifecycle/calibration.js +2 -0
  8. package/dist/lifecycle/calibration.js.map +1 -1
  9. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts +71 -0
  10. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts.map +1 -0
  11. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js +73 -0
  12. package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js.map +1 -0
  13. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts +71 -0
  14. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts.map +1 -0
  15. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js +73 -0
  16. package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js.map +1 -0
  17. package/dist/lifecycle/index.d.ts +1 -0
  18. package/dist/lifecycle/index.d.ts.map +1 -1
  19. package/dist/lifecycle/index.js +1 -0
  20. package/dist/lifecycle/index.js.map +1 -1
  21. package/dist/lifecycle/markets.d.ts +3 -1
  22. package/dist/lifecycle/markets.d.ts.map +1 -1
  23. package/dist/lifecycle/markets.js +20 -3
  24. package/dist/lifecycle/markets.js.map +1 -1
  25. package/dist/lifecycle/planner.d.ts.map +1 -1
  26. package/dist/lifecycle/planner.js +83 -54
  27. package/dist/lifecycle/planner.js.map +1 -1
  28. package/dist/lifecycle/presets.d.ts +9 -2
  29. package/dist/lifecycle/presets.d.ts.map +1 -1
  30. package/dist/lifecycle/presets.js +26 -5
  31. package/dist/lifecycle/presets.js.map +1 -1
  32. package/dist/lifecycle/progress.d.ts.map +1 -1
  33. package/dist/lifecycle/progress.js +26 -5
  34. package/dist/lifecycle/progress.js.map +1 -1
  35. package/dist/lifecycle/rpc.js +3 -2
  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 +119 -175
  40. package/dist/lifecycle/simulation.js.map +1 -1
  41. package/dist/lifecycle/transactions.d.ts +6 -0
  42. package/dist/lifecycle/transactions.d.ts.map +1 -1
  43. package/dist/lifecycle/transactions.js +39 -0
  44. package/dist/lifecycle/transactions.js.map +1 -1
  45. package/dist/lifecycle/types.d.ts +17 -4
  46. package/dist/lifecycle/types.d.ts.map +1 -1
  47. package/dist/lifecycle/types.js.map +1 -1
  48. package/dist/lifecycle/ufg-abi.d.ts +2386 -0
  49. package/dist/lifecycle/ufg-abi.d.ts.map +1 -0
  50. package/dist/lifecycle/ufg-abi.js +171 -0
  51. package/dist/lifecycle/ufg-abi.js.map +1 -0
  52. package/dist/lifecycle/ufg-config.d.ts +38 -0
  53. package/dist/lifecycle/ufg-config.d.ts.map +1 -0
  54. package/dist/lifecycle/ufg-config.js +75 -0
  55. package/dist/lifecycle/ufg-config.js.map +1 -0
  56. package/dist/lifecycle/ufg.d.ts +21 -0
  57. package/dist/lifecycle/ufg.d.ts.map +1 -0
  58. package/dist/lifecycle/ufg.js +98 -0
  59. package/dist/lifecycle/ufg.js.map +1 -0
  60. package/docs/launch-lifecycle.md +215 -32
  61. package/examples/.env.example +4 -0
  62. package/examples/README.md +35 -2
  63. package/examples/launch-example-support.ts +1 -0
  64. package/examples/launch-example.ts +1 -0
  65. package/examples/launch.ts +1 -0
  66. package/examples/ufg-launch-config.ts +31 -0
  67. package/package.json +1 -1
  68. package/src/lifecycle/abi.ts +1 -0
  69. package/src/lifecycle/calibration.ts +1 -0
  70. package/src/lifecycle/deployments/ufg-dynamic-pool-20261021.ts +74 -0
  71. package/src/lifecycle/deployments/ufg-fixed-pool-20261021.ts +74 -0
  72. package/src/lifecycle/index.ts +1 -0
  73. package/src/lifecycle/markets.ts +16 -3
  74. package/src/lifecycle/planner.ts +75 -51
  75. package/src/lifecycle/presets.ts +27 -6
  76. package/src/lifecycle/progress.ts +22 -5
  77. package/src/lifecycle/rpc.ts +3 -2
  78. package/src/lifecycle/simulation.ts +114 -166
  79. package/src/lifecycle/transactions.ts +38 -1
  80. package/src/lifecycle/types.ts +15 -5
  81. package/src/lifecycle/ufg-abi.ts +173 -0
  82. package/src/lifecycle/ufg-config.ts +77 -0
  83. package/src/lifecycle/ufg.ts +86 -0
@@ -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,
@@ -44,7 +45,9 @@ export type LifecycleLimitContext = { client: LifecycleRpcClient; account: Addre
44
45
  export type LifecycleLimits = {
45
46
  /** Optional tightening caps on the complete transaction gas envelope, including Nitro poster gas. */
46
47
  headroomBps?: number; chainGasLimit?: bigint; rpcGasLimit?: bigint; accountGasLimit?: bigint;
47
- maxCalldataBytes?: number; maxSimulationGas?: bigint;
48
+ maxCalldataBytes?: number;
49
+ /** Aggregate gas-used budget for one simulation request; defaults to 50M on chain 4663. */
50
+ maxSimulationGas?: bigint;
48
51
  chainId?: bigint; orchestrator?: Address; account?: Address; observedBlockNumber?: bigint; observedBlockHash?: Hash;
49
52
  /** External data fee not already charged in gas, called with exact calldata and the pinned block.
50
53
  * Nitro poster fees are included in gas and use the native NodeInterface instead. */
@@ -112,9 +115,12 @@ export type LifecycleSimulationStep = {
112
115
  };
113
116
  export type LifecycleSimulation = LifecycleProofOutcomes & {
114
117
  backend: "eth_simulateV1" | "controlled-fork" | "unavailable";
118
+ /** Admission/proved outcomes cover the successful prefix, not the deferred suffix. */
115
119
  confidence: "stateful" | "provisional"; admitted: boolean;
116
120
  blockNumber: bigint; blockHash: Hash; account: Address; chainId: bigint;
117
121
  steps: readonly LifecycleSimulationStep[]; limits: ResolvedLifecycleLimits;
122
+ /** Unproved suffix. These transactions receive no gas, price, estimate or admission. */
123
+ deferredTransactionIds: readonly string[];
118
124
  reason?: string; failedTransactionId?: string;
119
125
  failureCategory?: LifecycleFailureCategory; capacityConstraint?: LifecycleCapacityConstraint;
120
126
  };
@@ -156,6 +162,8 @@ export type PlannedLaunch = {
156
162
  plan: LaunchPlanV1; planHash: Hash; launchId: Hash; predictedToken: Address;
157
163
  tokenFactory: Address; tokenFactoryCodeHash: Hex;
158
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 };
159
167
  transactions: readonly LifecycleTransaction[]; prerequisites: readonly LifecycleFundingPrerequisite[];
160
168
  /** Sum of exact calldata bytes across the returned remaining commands, including approvals. */
161
169
  totalCalldataBytes: number;
@@ -163,7 +171,7 @@ export type PlannedLaunch = {
163
171
  /** Exact CREATE2 metadata captured from the final committed bound markets. */
164
172
  hookDeployments: readonly LifecyclePoolBoundHookDeployment[];
165
173
  progress: CanonicalLaunchProgress;
166
- preparationBatchSize: number; limits?: LifecycleLimitSource;
174
+ limits?: LifecycleLimitSource;
167
175
  /** Unstarted-launch admission choices only; never part of the committed plan or calldata. */
168
176
  allowTopologyGaps?: boolean; allowMissingPermanentTail?: boolean;
169
177
  };
@@ -171,6 +179,8 @@ export type PlanLaunchOptions = {
171
179
  client: LifecycleRpcClient; account: Address; plan: LaunchPlanV1; mode: LaunchExecutionMode;
172
180
  limits?: LifecycleLimitSource; fork?: ControlledLifecycleFork; receipts?: readonly LifecycleReceiptReference[];
173
181
  confirmations?: number; signal?: AbortSignal;
182
+ /** Opt in to the pinned UFG proxy; sender must match the nonce's principal namespace. */
183
+ ufg?: { config: UfgLaunchConfig };
174
184
  /** Unstarted only: permit interior gaps; opening containment, aligned ticks and the tail remain required. */
175
185
  allowTopologyGaps?: boolean;
176
186
  /** Unstarted only: waive the funded boundary tail; all other topology checks remain required. */
@@ -196,7 +206,7 @@ export type SimulateLaunchPlanOptions = {
196
206
  signal?: AbortSignal;
197
207
  };
198
208
  export type ReadLaunchProgressOptions = {
199
- client: LifecycleRpcClient; planned: Pick<PlannedLaunch, "plan" | "planHash" | "launchId" | "predictedToken" | "account" | "mode" | "confirmations">;
209
+ client: LifecycleRpcClient; planned: Pick<PlannedLaunch, "plan" | "planHash" | "launchId" | "predictedToken" | "account" | "mode" | "confirmations" | "ufg">;
200
210
  receipts?: readonly LifecycleReceiptReference[]; confirmations?: number;
201
211
  signal?: AbortSignal;
202
212
  };
@@ -204,8 +214,8 @@ export type BuildNextTransactionOptions = ReadLaunchProgressOptions & {
204
214
  planned: PlannedLaunch; action?: "continue" | "cancel"; limits?: LifecycleLimitSource; fork?: ControlledLifecycleFork;
205
215
  /** Optional active submission RPC. Only the immediate next exact transaction is estimated, read-only. */
206
216
  submissionClient?: LifecycleRpcClient;
207
- /** Untrusted reviewed next envelope. Fresh canonical semantics and complete
208
- * execution/headroom/affordability proof must accept its exact gas and gasPrice. */
217
+ /** Untrusted reviewed next envelope. Canonical identity and direct exact replay
218
+ * prove only this immediate transaction at its held gas and gasPrice. */
209
219
  reviewedTransaction?: LifecycleTransaction;
210
220
  };
211
221
  export class LifecyclePlanningError extends Error {
@@ -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
+ }
@@ -0,0 +1,86 @@
1
+ import { decodeFunctionResult, encodeFunctionData, keccak256, stringToHex, zeroAddress, type Address } from "viem";
2
+ import { lifecycleErc20Abi } from "./abi.js";
3
+ import { ufgLaunchProxyV1Abi, ufgTreasuryFactoryV1Abi } from "./ufg-abi.js";
4
+ import { buildLaunchTransactions } from "./transactions.js";
5
+ import { decodeAbyssLifecycleMarketConfig, encodeAbyssLifecycleMarketConfig, decodePoolBoundV4LifecycleMarketConfig } from "./markets.js";
6
+ import { getKnownLifecycleProfile, KnownLifecycleProfile } from "./presets.js";
7
+ import { LifecycleFundingKind, LifecycleTokenKind, LifecycleRewardMode, LifecycleMode, type LaunchPlanV1 } from "./schema.js";
8
+ import { LifecyclePlanningError, type BuildLaunchTransactionsOptions, type LifecycleRpcClient, type LifecycleTransaction } from "./types.js";
9
+ import { buildUfgFeeAssetPolicies, encodeUfgLaunchConfig, hashUfgLaunchConfig, isUfgProfile, UFG_DYNAMIC_ADAPTER_ID, UFG_FIXED_ADAPTER_ID, UFG_FIXED_PROFILE_ID, UFG_LAUNCH_PROXY_ADDRESS, UFG_TREASURY_FACTORY_ADDRESS, ufgPlanPrincipal, type UfgLaunchConfig } from "./ufg-config.js";
10
+
11
+ export { UFG_LAUNCH_PROXY_ADDRESS, UFG_TREASURY_FACTORY_ADDRESS, UFG_UPSTREAM_FACTORY_ADDRESS, UFG_ORCHESTRATOR_ADDRESS, UFG_FIXED_PROFILE_ID, UFG_DYNAMIC_PROFILE_ID, UFG_FIXED_ADAPTER_ID, UFG_DYNAMIC_ADAPTER_ID, isUfgProfile, ufgLaunchConfigComponents, encodeUfgLaunchConfig, decodeUfgLaunchConfig, hashUfgLaunchConfig, validateUfgLaunchConfig, ufgLaunchNonce, buildUfgFeeAssetPolicies, type UfgLaunchConfig } from "./ufg-config.js";
12
+
13
+ /** Offline proxy-specific admission. Live token/reserve code, registry and transfer checks still require simulation. */
14
+ export function validateUfgLaunchPlan(plan: LaunchPlanV1, config: UfgLaunchConfig, predictedToken: Address): void {
15
+ try {
16
+ ufgPlanPrincipal(plan);
17
+ encodeUfgLaunchConfig(config);
18
+ if (plan.token.kind !== LifecycleTokenKind.ERC20 || plan.token.rewardMode !== LifecycleRewardMode.None || plan.executorFeeBps !== 0 || plan.markets.length === 0 || plan.token.inventoryRecipient.toLowerCase() === UFG_LAUNCH_PROXY_ADDRESS.toLowerCase() || plan.buys.some((buy) => buy.recipient.toLowerCase() === UFG_LAUNCH_PROXY_ADDRESS.toLowerCase())) throw new Error("UFG requires ERC20/no rewards, zero executor fee, markets and external inventory/buy recipients");
19
+ const expected = buildUfgFeeAssetPolicies(predictedToken, config.reserveAssets);
20
+ if (plan.feeAssets.length !== expected.length || plan.feeAssets.some((policy, index) => {
21
+ const required = expected[index]!;
22
+ return policy.asset.toLowerCase() !== required.asset.toLowerCase() || policy.ownerBps !== required.ownerBps || policy.rewardsBps !== 0 || policy.burnBps !== required.burnBps;
23
+ })) throw new Error("UFG fee policies must burn all token fees and send all reserve fees to the owner, in ascending asset order");
24
+ const reserves = new Set(config.reserveAssets.map((asset) => asset.toLowerCase()));
25
+ const quotes = new Set(plan.markets.map((market) => market.quoteAsset.toLowerCase()));
26
+ if (reserves.size !== quotes.size || [...quotes].some((quote) => !reserves.has(quote))) throw new Error("Every reserve must be a market quote and every market quote a reserve");
27
+ const configHash = hashUfgLaunchConfig(config);
28
+ for (const market of plan.markets) {
29
+ if (market.configVersion === 1) {
30
+ const inner = decodeAbyssLifecycleMarketConfig(market.config);
31
+ const profile = getKnownLifecycleProfile({ chainId: plan.chainId, orchestrator: plan.orchestrator, key: inner.profile === 2 ? KnownLifecycleProfile.Abyss2 : KnownLifecycleProfile.Abyss3 });
32
+ if (market.adapterId.toLowerCase() !== keccak256(stringToHex("black-market.adapter.abyss-lifecycle.v1")) || (inner.profile !== 2 && inner.profile !== 3) || market.profileId.toLowerCase() !== profile?.profile.id || encodeAbyssLifecycleMarketConfig(inner).toLowerCase() !== market.config.toLowerCase()) throw new Error("UFG Abyss markets require canonical QUOTE or QUOTE_ORACLE config1 without a tail");
33
+ } else if (market.configVersion === 6) {
34
+ if (!isUfgProfile(market.profileId)) throw new Error("UFG config6 markets require an admitted UFG fixed or dynamic profile");
35
+ const inner = decodePoolBoundV4LifecycleMarketConfig(market.config, 6);
36
+ const adapterId = market.profileId.toLowerCase() === UFG_FIXED_PROFILE_ID ? UFG_FIXED_ADAPTER_ID : UFG_DYNAMIC_ADAPTER_ID;
37
+ if (market.adapterId.toLowerCase() !== adapterId || inner.profileId.toLowerCase() !== market.profileId.toLowerCase() || inner.version !== 6 || inner.feeMode !== 1 || inner.lpFeePips !== 0 || inner.ufgLaunchConfig === undefined || hashUfgLaunchConfig(inner.ufgLaunchConfig) !== configHash) throw new Error("Every UFG config6 market requires QuoteOnly, zero LP fee and the identical canonical proxy config tail");
38
+ } else throw new Error("UFG supports only canonical Abyss config1 and UFG pool-bound config6");
39
+ }
40
+ } catch (error) {
41
+ if (error instanceof LifecyclePlanningError && error.code === "INVALID_UFG_PLAN") throw error;
42
+ throw new LifecyclePlanningError("INVALID_UFG_PLAN", error instanceof Error ? error.message : "Invalid UFG launch plan");
43
+ }
44
+ }
45
+
46
+ export type BuildUfgLaunchTransactionsOptions = BuildLaunchTransactionsOptions & { config: UfgLaunchConfig };
47
+ /** Pure unsigned proxy commands; account is the principal encoded in plan.nonce. */
48
+ export function buildUfgLaunchTransactions(options: BuildUfgLaunchTransactionsOptions): LifecycleTransaction[] {
49
+ const { plan, config } = options;
50
+ const principal = ufgPlanPrincipal(plan);
51
+ encodeUfgLaunchConfig(config);
52
+ return buildLaunchTransactions(options).map((transaction) => {
53
+ const data = transaction.kind === "atomic" ? encodeFunctionData({ abi: ufgLaunchProxyV1Abi, functionName: "launchAtomic", args: [plan, config] })
54
+ : transaction.kind === "begin" ? encodeFunctionData({ abi: ufgLaunchProxyV1Abi, functionName: "beginLaunch", args: [plan, LifecycleMode.Staged, config] }) : transaction.data;
55
+ return { ...transaction, from: principal, to: UFG_LAUNCH_PROXY_ADDRESS, data, calldataBytes: (data.length - 2) / 2 };
56
+ });
57
+ }
58
+ export function buildUfgCancelTransaction({ plan, preparedMarkets = 0 }: { plan: LaunchPlanV1; preparedMarkets?: number }): LifecycleTransaction {
59
+ const data = encodeFunctionData({ abi: ufgLaunchProxyV1Abi, functionName: "cancelLaunch", args: [plan] });
60
+ return { id: "cancel", kind: "cancel", chainId: Number(plan.chainId), from: ufgPlanPrincipal(plan), to: UFG_LAUNCH_PROXY_ADDRESS, data, calldataBytes: (data.length - 2) / 2, value: 0n, dependencies: [], postconditions: [{ kind: "launch", phase: "Cancelled", preparedMarkets }] };
61
+ }
62
+ /** Exact summed proxy pulls, not escrow allowances. Current allowance/reset discovery belongs to planning. */
63
+ export function buildUfgApprovals(plan: LaunchPlanV1): LifecycleTransaction[] {
64
+ const principal = ufgPlanPrincipal(plan);
65
+ const totals = new Map<string, { asset: Address; amount: bigint }>();
66
+ for (const funding of plan.funding) {
67
+ if (funding.kind === LifecycleFundingKind.NativeWrap || BigInt(funding.inputAsset) === 0n) continue;
68
+ const asset = funding.kind === LifecycleFundingKind.ERC20 ? funding.asset : funding.inputAsset;
69
+ const amount = funding.kind === LifecycleFundingKind.ERC20 ? funding.amount : funding.inputAmount;
70
+ const key = asset.toLowerCase();
71
+ const entry = totals.get(key);
72
+ if (entry === undefined) totals.set(key, { asset, amount }); else entry.amount += amount;
73
+ }
74
+ const transactions = [...totals.values()].map(({ asset, amount }): LifecycleTransaction => {
75
+ const data = encodeFunctionData({ abi: lifecycleErc20Abi, functionName: "approve", args: [UFG_LAUNCH_PROXY_ADDRESS, amount] });
76
+ return { id: `approve:${asset}`, kind: "approve", chainId: Number(plan.chainId), from: principal, to: asset, data, calldataBytes: (data.length - 2) / 2, value: 0n, dependencies: [], postconditions: [{ kind: "allowance", asset, spender: UFG_LAUNCH_PROXY_ADDRESS, minimum: amount }] };
77
+ });
78
+ return transactions.map((transaction, index) => ({ ...transaction, dependencies: index === 0 ? [] : [transactions[index - 1]!.id] }));
79
+ }
80
+ /** Read-only upstream treasury lookup. No treasury is represented by undefined, not the zero address. */
81
+ export async function readUfgTreasury(client: LifecycleRpcClient, token: Address): Promise<Address | undefined> {
82
+ const data = encodeFunctionData({ abi: ufgTreasuryFactoryV1Abi, functionName: "treasuryOf", args: [token] });
83
+ const result = await client.request({ method: "eth_call", params: [{ to: UFG_TREASURY_FACTORY_ADDRESS, data }, "latest"] });
84
+ const treasury = decodeFunctionResult({ abi: ufgTreasuryFactoryV1Abi, functionName: "treasuryOf", data: result as `0x${string}` });
85
+ return treasury === zeroAddress ? undefined : treasury;
86
+ }