@black-market/sdk 0.11.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.
- package/README.md +17 -0
- 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 +42 -22
- 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.map +1 -1
- package/dist/lifecycle/progress.js +26 -5
- package/dist/lifecycle/progress.js.map +1 -1
- package/dist/lifecycle/simulation.d.ts.map +1 -1
- package/dist/lifecycle/simulation.js +4 -1
- package/dist/lifecycle/simulation.js.map +1 -1
- package/dist/lifecycle/types.d.ts +11 -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 +138 -0
- package/examples/README.md +16 -2
- 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 +37 -22
- package/src/lifecycle/presets.ts +11 -4
- package/src/lifecycle/progress.ts +22 -5
- package/src/lifecycle/simulation.ts +3 -1
- package/src/lifecycle/types.ts +6 -1
- package/src/lifecycle/ufg-abi.ts +173 -0
- package/src/lifecycle/ufg-config.ts +77 -0
- package/src/lifecycle/ufg.ts +86 -0
|
@@ -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
|
+
}
|