@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.
- package/README.md +96 -79
- package/dist/lifecycle/abi.d.ts +1 -0
- package/dist/lifecycle/abi.d.ts.map +1 -1
- package/dist/lifecycle/abi.js +1 -0
- package/dist/lifecycle/abi.js.map +1 -1
- package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts +71 -0
- package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.d.ts.map +1 -0
- package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js +73 -0
- package/dist/lifecycle/deployments/ufg-dynamic-pool-20261021.js.map +1 -0
- package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts +71 -0
- package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.d.ts.map +1 -0
- package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js +73 -0
- package/dist/lifecycle/deployments/ufg-fixed-pool-20261021.js.map +1 -0
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +1 -0
- package/dist/lifecycle/index.js.map +1 -1
- package/dist/lifecycle/markets.d.ts +3 -1
- package/dist/lifecycle/markets.d.ts.map +1 -1
- package/dist/lifecycle/markets.js +20 -3
- package/dist/lifecycle/markets.js.map +1 -1
- package/dist/lifecycle/planner.d.ts.map +1 -1
- package/dist/lifecycle/planner.js +101 -46
- package/dist/lifecycle/planner.js.map +1 -1
- package/dist/lifecycle/presets.d.ts +4 -2
- package/dist/lifecycle/presets.d.ts.map +1 -1
- package/dist/lifecycle/presets.js +11 -4
- package/dist/lifecycle/presets.js.map +1 -1
- package/dist/lifecycle/progress.d.ts +3 -1
- package/dist/lifecycle/progress.d.ts.map +1 -1
- package/dist/lifecycle/progress.js +145 -59
- package/dist/lifecycle/progress.js.map +1 -1
- package/dist/lifecycle/rpc.d.ts +8 -2
- package/dist/lifecycle/rpc.d.ts.map +1 -1
- package/dist/lifecycle/rpc.js +165 -9
- package/dist/lifecycle/rpc.js.map +1 -1
- package/dist/lifecycle/simulation.d.ts +1 -1
- package/dist/lifecycle/simulation.d.ts.map +1 -1
- package/dist/lifecycle/simulation.js +15 -11
- package/dist/lifecycle/simulation.js.map +1 -1
- package/dist/lifecycle/types.d.ts +23 -1
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lifecycle/types.js.map +1 -1
- package/dist/lifecycle/ufg-abi.d.ts +2386 -0
- package/dist/lifecycle/ufg-abi.d.ts.map +1 -0
- package/dist/lifecycle/ufg-abi.js +171 -0
- package/dist/lifecycle/ufg-abi.js.map +1 -0
- package/dist/lifecycle/ufg-config.d.ts +38 -0
- package/dist/lifecycle/ufg-config.d.ts.map +1 -0
- package/dist/lifecycle/ufg-config.js +75 -0
- package/dist/lifecycle/ufg-config.js.map +1 -0
- package/dist/lifecycle/ufg.d.ts +21 -0
- package/dist/lifecycle/ufg.d.ts.map +1 -0
- package/dist/lifecycle/ufg.js +98 -0
- package/dist/lifecycle/ufg.js.map +1 -0
- package/docs/launch-lifecycle.md +611 -1363
- package/docs/reference.md +332 -0
- package/examples/.env.example +3 -2
- package/examples/README.md +172 -539
- package/examples/launch-example-support.ts +11 -3
- package/examples/launch-example.ts +1 -1
- package/examples/launch-lifecycle-smoke.ts +1 -1
- package/examples/ufg-launch-config.ts +31 -0
- package/package.json +1 -1
- package/src/lifecycle/abi.ts +1 -0
- package/src/lifecycle/deployments/ufg-dynamic-pool-20261021.ts +74 -0
- package/src/lifecycle/deployments/ufg-fixed-pool-20261021.ts +74 -0
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/markets.ts +16 -3
- package/src/lifecycle/planner.ts +95 -45
- package/src/lifecycle/presets.ts +11 -4
- package/src/lifecycle/progress.ts +131 -51
- package/src/lifecycle/rpc.ts +158 -10
- package/src/lifecycle/simulation.ts +14 -10
- package/src/lifecycle/types.ts +15 -2
- package/src/lifecycle/ufg-abi.ts +173 -0
- package/src/lifecycle/ufg-config.ts +77 -0
- 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.
|
|
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 ?
|
|
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[] = [];
|
package/src/lifecycle/types.ts
CHANGED
|
@@ -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
|
+
}
|