# Contracts

Every deployed contract: functions, events and errors.

## FociV2LaunchFactory

`0xa93f9CeFD92A77e1EAffa3246B6F4DB91a5c5659`


### Functions an application calls

### `canLaunch(address)`

`0x58373f04` · `view` · view

Whether `launcher` may launch right now: true while the public gate is open, and true for whitelisted addresses while it is closed. The same predicate `launchToken` enforces on its caller, exposed so routers like FociV2LaunchAndBuy can hold their own callers to this single list instead of maintaining a second one.

`launchEnabled` is left FALSE by deployment. Always check this before showing a launch form.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `launcher` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `bool` |  |

### `createGraduatedPool(address)`

`0x2f53ef2f` · `nonpayable` · Permissionless and retryable.

Initializes the V4 pool with the swept reserves, mints a full-range position directly to the locker, and registers the pool with the meme hook. The curve already holds the pool's quote asset, so this seeds with exactly what it swept and needs no slippage bound. Permissionless and retryable: a launch stays in Swept until a seed succeeds, so a transient failure can never strand reserves.

Seeds the V4 pool and locks the position. Like `graduate` this normally runs inside the crossing buy — but it costs roughly 900k gas on its own, and under EIP-150's 63/64 rule a buy sized by a naive `estimateGas` starves it. When that happens the curve emits `AutoSeedFailed` and the launch sits in phase 1 with no tradeable venue until someone calls this. Run a keeper on that event. Send an explicit gas limit; estimation is reliable here because there is no try/catch to hide the cost.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `positionId` | `uint256` |  |


**Reverts**

- `WrongGraduationPhase` — not in the Swept phase
- `GraduationSeedNotViable`

### `getLaunchConfig(uint256)`

`0x1cad862d` · `view` · view

Returns one token launch configuration.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `id` | `uint256` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `(uint256,uint256,uint256,uint256,uint24,int24,bool)` |  |

### `getLaunchedToken(address)`

`0x3cf28b5a` · `view` · view

Returns the immutable record for a token created by this factory.

Returns a ZEROED struct for an unknown token rather than reverting — check `.exists`. This is also where you get the per-launch `curve` address, since curves have no fixed deployment.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `(address,address,address,address,address,uint256,uint24,int24,uint16,uint8,uint256,uint256,uint256,bool)` |  |

### `graduate(address)`

`0xff6d8d05` · `nonpayable` · Permissionless — anyone may call it.

Sweeps the curve's remaining quote and token reserves into this factory and halts curve trading. Purely internal to the curve's own balances, so it is safe for the curve to call this automatically the instant a buy crosses the graduation threshold.

Normally runs automatically inside the buy that crosses the threshold. Call it manually only when that inner attempt failed, which the curve reports by emitting `AutoGraduationFailed`.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |


**Reverts**

- `WrongGraduationPhase` — already swept
- `NotReadyToGraduate` — the curve is not finished

### `launchFee()`

`0xcf3cf573` · `view` · view


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `uint256` |  |

### `launchFeeToken()`

`0xbd03b5fc` · `view` · view

A flat charge on creating a launch, in `launchFeeToken`. Spam friction rather than revenue. Zero disables it outright: the payment path is skipped entirely, so nothing is pulled and no approval is needed while it is off. ERC-20 rather than native even where a chain's native asset is the same asset: the atomic launch router funds itself through `transferFrom`, and a native fee would make one call carry both an approval and attached value for what is economically one token.


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `address` |  |

### `launchToken((string,string,string,string,(string,string,string,string,string),address,uint16,bytes32,bytes32),uint256,address)`

`0xbc9bc035` · `nonpayable` · Permissionless, but gated by `canLaunch(msg.sender)` — check it before offering a launch UI.

Deploys a bonding curve and its launch token, wires them together, and records the launch. Trading starts immediately on the curve; the graduation pool's pairToken is fixed here, chosen by the caller.

**Approve first:** `factory` for launchFee() of launchFeeToken() (USDC).

Use this when there is NO opening buy. The atomic router reverts on a zero `quoteIn`, so it cannot be used as a plain deployer. Note the approval target differs from the router path: the factory pulls the fee from `msg.sender` itself. If `launchFee()` is zero, no approval is needed at all. A token launched this way starts with the creator holding none of its supply.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `params` | `(string,string,string,string,(string,string,string,string,string),address,uint16,bytes32,bytes32)` |  |
| `launchConfigId` | `uint256` |  |
| `pairToken` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |
| `curve` | `address` |  |


**Reverts**

- `NotWhitelisted` — `launchEnabled` is false and you are not a whitelisted launcher
- `InvalidLaunchConfigId` — no such config
- `InvalidTokenParams` — empty name or symbol
- `CreatorTaxTooHigh` — `creatorTaxBps` above `maxCreatorTaxBps()`
- `PairTokenNotApproved` — quote asset not approved by the owner
- `LaunchEconomicsMismatch(expected,actual)` — terms moved since you read `previewLaunchEconomics`
- `FailedDeployment` — you already used this `salt`; salts are namespaced per account
- ERC-20 revert on the fee transfer — insufficient allowance **to the factory**

### `pairTokenEconomics(address)`

`0x31082134` · `view` · view

Phantom reserve and graduation threshold in the QUOTE ASSET'S OWN DECIMALS (6 for USDC).


**Parameters**

| Name | Type | Description |
|---|---|---|
| `pairToken` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `phantomQuote` | `uint256` |  |
| `graduationThreshold` | `uint256` |  |
| `decimals` | `uint8` |  |

### `previewLaunchEconomics(uint256,address)`

`0xf718b78c` · `view` · view

Returns the economics digest a launch of `launchConfigId` in `pairToken` would produce right now, for a creator to pass back as TokenParams.expectedEconomics.

Reading the digest and launching in separate transactions still leaves the terms free to move in between; the pin is what makes that movement revert instead of silently repricing the launch.

Returns the digest to put in `TokenParams.expectedEconomics`. Fetch it in the same flow as the submit — it covers the launch fee, so an owner changing `setLaunchFee` between your quote and your signature invalidates it. Passing `bytes32(0)` waives the check entirely, which means accepting whatever terms are live when the transaction lands.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `launchConfigId` | `uint256` |  |
| `pairToken` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `bytes32` |  |


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `acceptOwnership()` | `0x79ba5097` | nonpayable |
| `addLaunchConfig((uint256,uint256,uint256,uint256,uint24,int24,bool))` | `0x0e5b0aae` | nonpayable |
| `approvedPairTokens(address)` | `0x9831705e` | view |
| `cancelCreatorFeeRecipientChange(address)` | `0x6e47a188` | nonpayable |
| `CREATOR_FEE_RECIPIENT_EXECUTION_WINDOW()` | `0x02d4753d` | view |
| `CREATOR_FEE_RECIPIENT_TIMELOCK()` | `0x5a83b00a` | view |
| `executeCreatorFeeRecipientChange(address)` | `0x3d3d2d58` | nonpayable |
| `feeEscrow()` | `0xc4b7de97` | view |
| `forceSweptGraduation(address)` | `0x7aed273e` | nonpayable |
| `getLaunchFeePolicy(address)` | `0x470ef5fc` | view |
| `GRADUATION_RESCUE_DELAY()` | `0x2d1250b8` | view |
| `graduationExecutor()` | `0xcc6d7a39` | view |
| `graduationGuard()` | `0x496aa100` | view |
| `launchConfigCount()` | `0xae72d871` | view |
| `launchDeployer()` | `0x858f5964` | view |
| `launchEnabled()` | `0x236a4afb` | view |
| `launchForwarder()` | `0x9b924452` | view |
| `launchTokenFor((string,string,string,string,(string,string,string,string,string),address,uint16,bytes32,bytes32),uint256,address,address)` | `0x266101cb` | nonpayable |
| `locker()` | `0xd7b96d4e` | view |
| `maxCreatorTaxBps()` | `0xf325a5fb` | view |
| `memeHook()` | `0x6651812c` | view |
| `owner()` | `0x8da5cb5b` | view |
| `pendingCreatorFeeRecipient(address)` | `0x9beacf4a` | view |
| `pendingOwner()` | `0xe30c3978` | view |
| `permit2()` | `0x12261ee7` | view |
| `poolManager()` | `0xdc4c90d3` | view |
| `positionManager()` | `0x791b98bc` | view |
| `renounceOwnership()` | `0x715018a6` | pure |
| `rescueCurveFees(address)` | `0x189eb0f5` | nonpayable |
| `rescueSweptGraduation(address,address)` | `0xdbcb9c76` | nonpayable |
| `setCreatorFeeRecipient(address,address)` | `0xe102c9aa` | nonpayable |
| `setGraduationExecutor(address)` | `0xfbec2d8b` | nonpayable |
| `setLaunchDeployer(address)` | `0x3a9391e8` | nonpayable |
| `setLaunchEnabled(bool)` | `0xf56f05b2` | nonpayable |
| `setLaunchFee(address,uint256)` | `0x6e51833f` | nonpayable |
| `setLaunchForwarder(address)` | `0x767b7c16` | nonpayable |
| `setMaxCreatorTaxBps(uint256)` | `0x2260aead` | nonpayable |
| `setPairTokenApproved(address,bool)` | `0x8763e3dc` | nonpayable |
| `setPairTokenEconomics(address,uint256,uint256,uint8)` | `0x092c08bd` | nonpayable |
| `setWhitelistedLauncher(address,bool)` | `0x366f0f3e` | nonpayable |
| `transferCreatorFeeRecipient(address,address)` | `0x2931861b` | nonpayable |
| `transferOwnership(address)` | `0xf2fde38b` | nonpayable |
| `updateLaunchConfig(uint256,(uint256,uint256,uint256,uint256,uint24,int24,bool))` | `0xe73e334a` | nonpayable |
| `whitelistedLaunchers(address)` | `0xda3eda65` | view |


### Events

| Event | topic0 |
|---|---|
| `CreatorFeeRecipientChangeCancelled(address,address)` | `0xbe2de91c1cbef653c760573fff8355c0c851d35ed2a898342b4db556301cccf4` |
| `CreatorFeeRecipientChangeProposed(address,address,address,uint256,uint256)` | `0x7f119e44c84a715429bee60d30ad2e14afdef6c60bb1a7eaa01290ecf6d1b2e5` |
| `CreatorFeeRecipientUpdated(address,address,address)` | `0x308c390ed1ab5873392818e036cabdf408bc8ad042fbaead3108954ff75ba980` |
| `GraduationExecutorSet(address)` | `0xac04674474e93058fae25e6df5dd94f57cdcacfe560a182a2eefc8c6006fbf6f` |
| `GraduationTokensPermanentlyLocked(address,uint256)` | `0xa0a18f5bf205becee8b268d7cf69addab8548ae8ef361791464cf0e0e17c1361` |
| `LaunchConfigAdded(uint256)` | `0xedd96c570c6e5ef9add0378e59df53579a283889dc5dab6440ef6eca2ee6c8ce` |
| `LaunchConfigUpdated(uint256)` | `0x2f8ba78ae68cfd0c82c7756c540eaf4eead3341aef9ccebcb91d546bff10d62b` |
| `LaunchDeployerSet(address)` | `0xd5ea7aa3e328a0594dcf6914cd9e5369779efaa194ee4dd4c5afcad4f4ebbb0c` |
| `LaunchEnabledUpdated(bool)` | `0x4f1ea5016c51c2f82324e00e9b8a4a95ee5aeaa10c653dabaec5f1bc9047ba0b` |
| `LaunchFeeUpdated(address,uint256)` | `0xd0766d3f1431146228fe8edef25f27842a1669c91d46e4af1b73405b354489a5` |
| `LaunchForceSwept(address)` | `0x52c1a28345695afc7f6b7629133124dec5d61ee745affd65e4fd2a776bc05840` |
| `LaunchForwarderSet(address)` | `0x56b32d3633fed72f97c4df44a78b5fa04f1d662d4bddebcd8a9b216d26d093ad` |
| `LaunchGraduationRescued(address,address,uint256,uint256)` | `0x7017304fdd491394686dce984eac721f0be1a22228346210f16694772bde44ca` |
| `LaunchSwept(address,uint256,uint256)` | `0xcdb72f157fd3666758a6ce201387ffb52038c7562e4fff352828da1096c4b6b4` |
| `MaxCreatorTaxUpdated(uint256)` | `0x3e99ceb3e222d2214d53dacca902810db845f156f78152fdc076be628c4e9a40` |
| `OwnershipTransferred(address,address)` | `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` |
| `OwnershipTransferStarted(address,address)` | `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` |
| `PairTokenApprovalUpdated(address,bool)` | `0x060d1992d069dc524985f328329aae36102a017c59733c5c91fc0691ee0703b6` |
| `PairTokenEconomicsUpdated(address,uint256,uint256,uint8)` | `0x67d517ee0e305d608b8410ddef27bbd2ed964d843d9b936e84ea2ad1bd65e5d1` |
| `PoolGraduated(address,uint256,uint256,uint256)` | `0x0a44ef75df69c534f43cd6c1aa3ef8983065fe5fe79ef9e79f6494e6f258c259` |
| `TokenLaunched(address,address,address,address,uint256,uint256)` | `0x8d4aad4953d0ca700d468f3753aa14432d1b35b43ec6409f051fb6aa43a89607` |
| `WhitelistedLauncherUpdated(address,bool)` | `0xef2b562a67f01ed4b7c4265ec09b539039c6d5dd7e752191d3940508c3dc0068` |


### Errors

| Error | Selector |
|---|---|
| `AlreadySet()` | `0xa741a045` |
| `CombinedFeeTooHigh()` | `0x49e55bcb` |
| `CoreLpFeeMustBeZero()` | `0x85258712` |
| `CreatorTaxTooHigh()` | `0x9ad465dc` |
| `CurveFeeTooHigh()` | `0x4e222a24` |
| `CurveNotQuotable()` | `0x95e32dab` |
| `FeeTransferFailed()` | `0x4033e4e3` |
| `GraduationExecutorNotSet()` | `0xd43cabc3` |
| `GraduationRescueTooEarly(uint256)` | `0xbdcd75af` |
| `GraduationSeedNotViable()` | `0x2c37d0eb` |
| `GraduationStillViable()` | `0x6d3bcfe5` |
| `InexactTransfer(address,uint256,uint256)` | `0x495a9962` |
| `InvalidBasisPoints()` | `0x800c7e91` |
| `InvalidGraduationThreshold()` | `0x2bb8bdd6` |
| `InvalidLaunchConfigId()` | `0x68b42c59` |
| `InvalidPhantomQuote()` | `0x2b7ad4f8` |
| `InvalidTickSpacing()` | `0x270815a0` |
| `InvalidTokenParams()` | `0x374852ca` |
| `LaunchConfigDisabled()` | `0xa8b63076` |
| `LaunchDependenciesNotWired()` | `0x1de25df3` |
| `LaunchDeployerNotSet()` | `0x57332dcf` |
| `LaunchEconomicsMismatch(bytes32,bytes32)` | `0xecb27319` |
| `LaunchFeeTokenNotSet()` | `0x52660db0` |
| `NoPendingChange()` | `0xa3fef2f8` |
| `NotCreatorFeeRecipient()` | `0xb9f93944` |
| `NothingToGraduate()` | `0xc2074c46` |
| `NotLaunchForwarder()` | `0xea9eaa96` |
| `NotReadyToGraduate()` | `0xffa32558` |
| `NotWhitelisted()` | `0x584a7938` |
| `OwnableInvalidOwner(address)` | `0x1e4fbdf7` |
| `OwnableUnauthorizedAccount(address)` | `0x118cdaa7` |
| `OwnershipCannotBeRenounced()` | `0x2fab92ca` |
| `PairTokenDecimalsMismatch(uint8,uint8)` | `0x4e3de34f` |
| `PairTokenDecimalsUnavailable()` | `0xe43c14ca` |
| `PairTokenEconomicsInvalid()` | `0x764c63c8` |
| `PairTokenNotApproved()` | `0x49285dfb` |
| `PairTokenValidationFailed()` | `0x26fbfa60` |
| `ReentrancyGuardReentrantCall()` | `0x3ee5aeb5` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `SqrtPriceOutOfBounds()` | `0x582157bb` |
| `SupplyTooHigh()` | `0xacb9fa2b` |
| `SupplyTooLow()` | `0xc0b4e373` |
| `TimelockExpired(uint256)` | `0xb79d40e8` |
| `TimelockNotElapsed(uint256)` | `0x810c4f2a` |
| `TokenNotFound()` | `0xcbdb7b30` |
| `UnsupportedPrice()` | `0xdd737e7c` |
| `WrongGraduationPhase()` | `0x9465dbd4` |
| `ZeroAddress()` | `0xd92e233d` |
| `ZeroAmount()` | `0x1f2a2005` |

---
## FociV2BondingCurve

Deployed **once per launch** — no fixed address. Read it from `factory.getLaunchedToken(token)`.


### Functions an application calls

### `buy(uint256,uint256,address)`

`0x59a87bc1` · `payable` · Permissionless. Reverts once the launch has graduated.

Buys the launch token with this launch's quote asset. The fee is always taken from the quote leg, so this curve never holds a memecoin-denominated fee.

`quoteIn` must equal `msg.value` for a native launch, and must be accompanied by no value at all for an ERC-20 launch. The credited amount for an ERC-20 is the observed balance delta rather than the requested amount, so a fee-on-transfer quote asset cannot make the curve promise reserves it never received. A buy that would take the curve past its reserved allocation is filled only up to that allocation, charged for what it actually received, and refunded the difference. It is deliberately not rejected: the last buy of a launch is the one most likely to be sized against a state someone else has already moved, and reverting would let anyone grief it by slipping a small buy in ahead. Partial fills reinterpret `minTokensOut` as a bound on price rather than on quantity, since a caller who spends less than they offered cannot expect the whole quantity they asked for. The requirement is that the price paid is no worse than the price implied by the caller's own arguments, and when nothing is clamped it reduces exactly to `tokensOut >= minTokensOut`.

**Approve first:** `curve` for quoteIn of the quote asset (USDC).

`minTokensOut` is a PRICE bound, not a quantity bound. A buy that would exceed the remaining allocation is clamped rather than reverted, and the remainder is refunded to `msg.sender` in the same transaction — so you can safely overshoot the graduation threshold.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `quoteIn` | `uint256` |  |
| `minTokensOut` | `uint256` |  |
| `recipient` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `tokensOut` | `uint256` |  |


**Reverts**

- `CurveGraduated` — the curve is closed; trade the V4 pool instead
- `SlippageExceeded(tokensOut,minTokensOut)` — the effective price broke your bound
- `UnexpectedNativeValue` — sent ETH on an ERC-20-quoted launch; `msg.value` must be 0
- `ZeroAmount` — the transfer delivered nothing

### `buy(uint256,uint256,address,address)`

`0x82b2a559` · `payable` · Permissionless. Reverts once the launch has graduated.

Buys with a referrer attached.

The referrer is only consulted the first time `recipient` trades with one; after that the binding in the registry stands and this argument is ignored, so passing a fresh referrer cannot poach an existing relationship. An unusable referrer (the recipient themselves, or someone the recipient already refers) reverts rather than being dropped, because it is an argument the caller chose to supply and silently charging them the undiscounted fee would be worse.

**Approve first:** `curve` for quoteIn of the quote asset (USDC).

As above, with a referrer bound to `recipient` (not to `msg.sender`). The binding is written only on that address's first referred trade and is permanent thereafter. An unusable referrer REVERTS THE WHOLE BUY — `SelfReferral` and `ReciprocalReferral` are not swallowed — so resolve and validate a referrer before putting it in the call.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `quoteIn` | `uint256` |  |
| `minTokensOut` | `uint256` |  |
| `recipient` | `address` |  |
| `referrer` | `address` | The account to credit for this recipient's trades, or the zero address to trade under whatever binding already exists. |


**Returns**

| Name | Type | Description |
|---|---|---|
| `tokensOut` | `uint256` |  |


**Reverts**

- `SelfReferral` — referrer is the recipient
- `ReciprocalReferral` — the recipient already refers that address
- everything the 3-argument overload throws

### `getReserves()`

`0x0902f1ac` · `view` · view

Returns the curve's current tradeable reserves, excluding fees pending sweep.

Returns the VIRTUAL reserves — `quoteReserve` includes the phantom reserve. For the amount actually raised use `realQuoteReserve()`.


**Returns**

| Name | Type | Description |
|---|---|---|
| `quoteReserve_` | `uint256` |  |
| `tokenReserve_` | `uint256` |  |

### `graduated()`

`0xe7c2b772` · `view` · view


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `bool` |  |

### `quoteReserve()`

`0x9da771f4` · `view` · view

Tradeable quote reserve only, matching IFociV2BondingCurve.


**Returns**

| Name | Type | Description |
|---|---|---|
| `quoteReserve_` | `uint256` |  |

### `readyToGraduate()`

`0xc68360a5` · `view` · view

True once the curve's sellable allocation has been bought out.

Equivalent to the real quote reserve reaching `graduationThreshold`, since the reserved balance is derived from that same point. Expressed against the token side because that is the one a buy cannot overshoot: the quote side is a floor that a large trade could sail past, while the token side is a hard stop the curve refuses to cross.

True when the sellable allocation reaches zero, which is by construction the same point as the real quote reserve reaching the graduation threshold.


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `bool` |  |

### `realQuoteReserve()`

`0x4f1f58fd` · `view` · view

Returns physically held tradeable quote asset, excluding virtual liquidity and balances already earmarked as fees or creator tax.


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `uint256` |  |

### `sell(uint256,uint256,address)`

`0xd04c6983` · `nonpayable` · Permissionless. Closes the instant `readyToGraduate()` is true.

Sells the launch token back to the curve for the quote asset. The fee is taken from the quote output, so it is always quote-denominated here too.

Closed once the sellable allocation is exhausted, not merely once `graduated` is set. `_tryAutoGraduate` swallows a failed graduation so a problem there cannot take the crossing buy down with it, which leaves a window where the curve is ready but the flag is still false. `buy` already refuses that state through its own `sellable == 0` check, and `sell` has to match: `graduate` hands the pool whatever `trackedTokens` holds, so a sell landing in the window would put tokens back on the curve and take quote off it, and the pool would then be seeded deeper and cheaper than the reserved allocation fixes it at. The deterministic graduation price only holds if the window is closed on both sides. This cannot strand a holder. `graduate` is permissionless, so anyone blocked here can settle the launch themselves in the same transaction and trade the V4 pool instead.

**Approve first:** `curve` for tokensIn of the MEMECOIN (18 decimals).

Unlike buy, `minQuoteOut` is a strict QUANTITY bound. The sell side shuts the moment the allocation is exhausted — before the `graduated` flag is even set — so a sell can start reverting with `CurveGraduated` while the UI still shows a live curve. Approve the CURVE for the memecoin, not the factory.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `tokensIn` | `uint256` |  |
| `minQuoteOut` | `uint256` |  |
| `recipient` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `quoteOut` | `uint256` |  |


**Reverts**

- `CurveGraduated` — the allocation is exhausted or the curve has graduated
- `SlippageExceeded(quoteOut,minQuoteOut)`
- `ZeroAmount`

### `sellableTokens()`

`0x808bcddc` · `view` · view

Tokens still available to buy before the curve graduates.


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `uint256` |  |


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `creatorTaxBalance()` | `0xdb2bd533` | view |
| `creatorTaxBps()` | `0xc1bb8901` | view |
| `deployer()` | `0xd5f39488` | view |
| `factory()` | `0xc45a0155` | view |
| `feeBps()` | `0x24a9d853` | view |
| `feeEscrow()` | `0xc4b7de97` | view |
| `feePolicy()` | `0x82589038` | view |
| `graduate(address)` | `0xff6d8d05` | nonpayable |
| `graduationThreshold()` | `0x8b0bc501` | view |
| `initialize(address)` | `0xc4d66de8` | nonpayable |
| `isNativeQuote()` | `0xdc08e094` | view |
| `launchedAt()` | `0xbf56b371` | view |
| `launchSupply()` | `0x3f7ed6b7` | view |
| `maxInternalPriceImpactBps()` | `0x90addc1e` | view |
| `pairToken()` | `0x3de35b79` | view |
| `phantomQuote()` | `0xc57eadfc` | view |
| `protocolFeeRecipient()` | `0x64df049e` | view |
| `protocolFeeShareBps()` | `0x9040f866` | view |
| `quoteFeeBalance()` | `0xed479c47` | view |
| `referralDiscountBps()` | `0x30ab6943` | view |
| `referralRegistry()` | `0x4e627e62` | view |
| `referralShareBps()` | `0x47c9bc2d` | view |
| `rescueFees()` | `0x52920587` | nonpayable |
| `reservedTokens()` | `0x15a55347` | view |
| `setCreatorFeeRecipient(address)` | `0x7b04ea62` | nonpayable |
| `sweepFees()` | `0xd113b95c` | nonpayable |
| `token()` | `0xfc0c546a` | view |
| `tokenReserve()` | `0xcbcb3171` | view |
| `trackedQuote()` | `0xca52b0b7` | view |
| `trackedTokens()` | `0x4c37ef23` | view |


### Events

| Event | topic0 |
|---|---|
| `AutoGraduationFailed(address,uint256)` | `0xe2cd2f31ebc05ec28640102987f4c8fc5f20e269e1b3aa82577f3f2f0e35c7c6` |
| `AutoSeedFailed(address,uint256)` | `0x2cbe77dadc7f8418071409bebfd71778263eecb998af52aa5c9e27b995a71676` |
| `CreatorFeeRecipientUpdated(address,address)` | `0x2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd19` |
| `CurveBuy(address,address,uint256,uint256,uint256,uint256)` | `0xec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455` |
| `CurveBuyRefunded(address,uint256)` | `0xa69e8258ccc7b9bbb70ab953fc2d1062b4ee28b8ca827534097e1732e87b0262` |
| `CurveCompleted(address,uint256,uint256)` | `0xf8d37a90738ae063b8b8058b66f5880cf3cf7ab0c5d4fa78219696591dfbfb67` |
| `CurveSell(address,address,uint256,uint256,uint256,uint256)` | `0x8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df` |
| `FeesRescued(address,address,uint256,uint256)` | `0x6460dc5c867a0678a8bcc5e64f629fae539901c53a4a8b42fe21d7a6c5e6437d` |
| `FeesSwept(uint256,uint256)` | `0xaf739f46ca7a23c9f259838ec2c5249acf4e1cf9fe68a46f77c3dfa452eda605` |
| `Initialized(address)` | `0x908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6` |
| `ReferralFeePaid(address,address,uint256)` | `0xde9bddf476dde28b26de9d0b38bb9811ebb9d4945cd0c7feadd215c28fe09717` |


### Errors

| Error | Selector |
|---|---|
| `AlreadyGraduated()` | `0xe6a0d45f` |
| `AlreadyInitialized()` | `0x0dc149f0` |
| `CurveGraduated()` | `0x025ac17e` |
| `InsufficientInputAmount()` | `0x098fb561` |
| `InsufficientLiquidity()` | `0xbb55fd27` |
| `InsufficientOutputAmount()` | `0x42301c23` |
| `InvalidFeePolicy()` | `0x7a34030f` |
| `InvalidLaunchEconomics()` | `0xbc0ecfe3` |
| `NativeValueMismatch(uint256,uint256)` | `0xbc760cfe` |
| `NotFactory()` | `0x32cc7236` |
| `NotFeeSweepOperator()` | `0x8d42130c` |
| `NotInitialized()` | `0x87138d5c` |
| `NotReadyToGraduate()` | `0xffa32558` |
| `ReentrancyGuardReentrantCall()` | `0x3ee5aeb5` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `SlippageExceeded(uint256,uint256)` | `0x71c4efed` |
| `TransferFailed()` | `0x90b8ec18` |
| `UnexpectedNativeValue()` | `0xe0aeda7d` |
| `ZeroAddress()` | `0xd92e233d` |
| `ZeroAmount()` | `0x1f2a2005` |

---
## FociV2LauncherToken

Deployed **once per launch** — no fixed address. Read it from `factory.getLaunchedToken(token)`.


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `allowance(address,address)` | `0xdd62ed3e` | view |
| `approve(address,uint256)` | `0x095ea7b3` | nonpayable |
| `balanceOf(address)` | `0x70a08231` | view |
| `burn(uint256)` | `0x42966c68` | nonpayable |
| `burnFrom(address,uint256)` | `0x79cc6790` | nonpayable |
| `curve()` | `0x7165485d` | view |
| `decimals()` | `0x313ce567` | view |
| `deployer()` | `0xd5f39488` | view |
| `description()` | `0x7284e416` | view |
| `getTokenInfo()` | `0xabb1dc44` | view |
| `launchFactory()` | `0x536dac9b` | view |
| `logo()` | `0xfb7f21eb` | view |
| `name()` | `0x06fdde03` | view |
| `socials()` | `0x53cd512a` | view |
| `symbol()` | `0x95d89b41` | view |
| `totalSupply()` | `0x18160ddd` | view |
| `transfer(address,uint256)` | `0xa9059cbb` | nonpayable |
| `transferFrom(address,address,uint256)` | `0x23b872dd` | nonpayable |


### Events

| Event | topic0 |
|---|---|
| `Approval(address,address,uint256)` | `0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925` |
| `Transfer(address,address,uint256)` | `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` |


### Errors

| Error | Selector |
|---|---|
| `ERC20InsufficientAllowance(address,uint256,uint256)` | `0xfb8f41b2` |
| `ERC20InsufficientBalance(address,uint256,uint256)` | `0xe450d38c` |
| `ERC20InvalidApprover(address)` | `0xe602df05` |
| `ERC20InvalidReceiver(address)` | `0xec442f05` |
| `ERC20InvalidSender(address)` | `0x96c6fd1e` |
| `ERC20InvalidSpender(address)` | `0x94280d62` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2LaunchAndBuy

`0xE4A165a52A6033ee0C1b3B6dA83f72AbA1707349`


### Functions an application calls

### `launchAndBuy((string,string,string,string,(string,string,string,string,string),address,uint16,bytes32,bytes32),uint256,address,uint256,uint256,address)`

`0x32b6091a` · `payable` · Permissionless, but `factory.canLaunch(msg.sender)` must hold — routing through the router does not widen the gate.

Launches a token and immediately buys `quoteIn` of its curve for `recipient`, both in this transaction.

A native launch carries the opening buy as `msg.value`. An ERC-20 launch carries no value at all and the buy is pulled from the caller, who must have approved this contract for `quoteIn` first.

**Approve first:** `launchAndBuy` for launchFee() + quoteIn — ONE approval covers both of launchFeeToken() (USDC).

Deploys the token and performs the creator's opening buy in one transaction. Two things differ from the direct path: `creatorFeeRecipient` may NOT be zero here (the direct path defaults it to the caller), and `quoteIn` may not be zero — the router exists to buy. GAS: if the opening buy crosses the graduation threshold the curve tries to seed the V4 pool inside this same transaction, and `eth_estimateGas` cannot size that — the seed is a best-effort try/catch, so a simulation in which it fails still succeeds overall and returns a limit too small for it to work. Send an explicit generous gas limit.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `params` | `(string,string,string,string,(string,string,string,string,string),address,uint16,bytes32,bytes32)` | Launch parameters, forwarded to the factory untouched. Set `creatorFeeRecipient` to the wallet that should earn the launch's fees, and `expectedEconomics` to the value `previewLaunchEconomics` returned, which still pins the terms as it would on a direct launch. |
| `launchConfigId` | `uint256` | Factory launch config to launch against. |
| `pairToken` | `address` | Quote asset, or the zero address for a native launch. |
| `quoteIn` | `uint256` | Amount of the quote asset to spend on the opening buy. An amount past what the curve can sell is clamped by the curve and the remainder comes back to the caller. |
| `minTokensOut` | `uint256` | Slippage bound on the opening buy. The curve prices a clamped fill against this too, so a buy sized to take the whole allocation can still set a meaningful floor. |
| `recipient` | `address` | Receives the purchased tokens. |


**Returns**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |
| `curve` | `address` |  |
| `tokensOut` | `uint256` |  |


**Reverts**

- `NotApprovedLauncher` — the factory's launch gate is closed for you
- `ZeroAddress` — `recipient` or `params.creatorFeeRecipient` is zero
- `ZeroAmount` — `quoteIn` is zero; use `factory.launchToken` instead
- everything `launchToken` throws, plus an allowance failure against **the router**


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `acceptOwnership()` | `0x79ba5097` | nonpayable |
| `factory()` | `0xc45a0155` | view |
| `owner()` | `0x8da5cb5b` | view |
| `pendingOwner()` | `0xe30c3978` | view |
| `renounceOwnership()` | `0x715018a6` | nonpayable |
| `rescue(address,address)` | `0x4fdf5d1d` | nonpayable |
| `transferOwnership(address)` | `0xf2fde38b` | nonpayable |


### Events

| Event | topic0 |
|---|---|
| `Launched(address,address,address,address,uint256,uint256)` | `0xdcacba5e347ae7abd91cb519eb877af8fa7774e347b85dd3ddcd24a2ba8cdf37` |
| `OwnershipTransferred(address,address)` | `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` |
| `OwnershipTransferStarted(address,address)` | `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` |
| `Rescued(address,address,uint256)` | `0x3af790fafda720819b2fc6e15090606e81154e0ac9a92d38ecad006d99d20ecc` |


### Errors

| Error | Selector |
|---|---|
| `NativeValueMismatch(uint256,uint256)` | `0xbc760cfe` |
| `NotApprovedLauncher()` | `0x502ba015` |
| `OwnableInvalidOwner(address)` | `0x1e4fbdf7` |
| `OwnableUnauthorizedAccount(address)` | `0x118cdaa7` |
| `ReentrancyGuardReentrantCall()` | `0x3ee5aeb5` |
| `RefundFailed()` | `0xf0c49d44` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `ZeroAddress()` | `0xd92e233d` |
| `ZeroAmount()` | `0x1f2a2005` |

---
## FociV2MemeHook

`0x527129aB10Fa3163629A32c4E3Ab7a98ba28e044`


### Functions an application calls

### `claimReferralFees(address,address)`

`0xcf893acc` · `nonpayable` · Permissionless — anyone may settle anyone's accrual into the escrow.

Pays a referrer their accrued fees for one currency into the escrow. Permissionless: the amount and destination are fixed by the ledger, so who triggers the settlement does not matter.

Deliberately not settled inside `afterSwap`. An escrow credit is an external call plus an approval, and putting it on the swap path would charge every trader for it. This mirrors how the pool's own fees are batched into `sweepPoolFees` rather than distributed per swap.

Two steps, not one: this moves the accrual into the escrow, then the referrer calls `feeEscrow.claimToken` to withdraw. Returns 0 and does nothing when the ledger is empty.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `referrer` | `address` |  |
| `currency` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `amount` | `uint256` |  |

### `currentFeePolicy()`

`0x89a69bd8` · `view` · view

Returns the policy terms new launches snapshot immutably.

Live policy. A launch freezes a copy of this at creation, so an existing launch is unaffected by later changes.


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `(address,uint16,uint16,uint16,uint16,uint16)` |  |

### `pendingReferral(address,address)`

`0xd85b2777` · `view` · view


**Parameters**

| Name | Type | Description |
|---|---|---|
| `referrer` | `address` |  |
| `currency` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `amount` | `uint256` |  |

### `sweepPoolFees(bytes32,uint256)`

`0xebe51768` · `nonpayable` · The fee-sweep operator, or the pool's creator.

Converts any pending memecoin-denominated fee into the pool's quote currency against the pool's own liquidity, then splits the combined quote-currency total between protocol and creator using the live policy, exactly mirroring the bonding curve's own sweep. The trusted sweep operator is required whenever the sweep would execute an internal conversion. The creator may still distribute already-quoted fees when no internal swap is needed.

If any memecoin-denominated fee is pending, only the operator may call and `minConversionQuoteOut` must be non-zero — the sweep converts inventory against the pool's own liquidity and needs a slippage bound.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `poolId` | `bytes32` |  |
| `minConversionQuoteOut` | `uint256` |  |


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `acceptOwnership()` | `0x79ba5097` | nonpayable |
| `afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)` | `0x9f063efc` | nonpayable |
| `afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)` | `0xe1b4af69` | nonpayable |
| `afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)` | `0x6fe7e6eb` | nonpayable |
| `afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)` | `0x6c2bbe7e` | nonpayable |
| `afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)` | `0xb47b2fb1` | nonpayable |
| `beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)` | `0x259982e5` | nonpayable |
| `beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)` | `0xb6a8b0fa` | nonpayable |
| `beforeInitialize(address,(address,address,uint24,int24,address),uint160)` | `0xdc98354e` | nonpayable |
| `beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)` | `0x21d0ee70` | nonpayable |
| `beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)` | `0x575e24b4` | nonpayable |
| `factory()` | `0xc45a0155` | view |
| `feeEscrow()` | `0xc4b7de97` | view |
| `feeSweepOperator()` | `0x8a36a6bb` | view |
| `getHookPermissions()` | `0xc4e833ce` | pure |
| `hookFeeBps()` | `0xea26abcf` | view |
| `launches(bytes32)` | `0xad091230` | view |
| `maxInternalPriceImpactBps()` | `0x90addc1e` | view |
| `owner()` | `0x8da5cb5b` | view |
| `pendingCreatorTax(bytes32,address)` | `0xc8eaa792` | view |
| `pendingFees(bytes32,address)` | `0x359b4f30` | view |
| `pendingOwner()` | `0xe30c3978` | view |
| `poolManager()` | `0xdc4c90d3` | view |
| `protocolFeeRecipient()` | `0x64df049e` | view |
| `protocolFeeShareBps()` | `0x9040f866` | view |
| `referralDiscountBps()` | `0x30ab6943` | view |
| `referralRegistry()` | `0x4e627e62` | view |
| `referralShareBps()` | `0x47c9bc2d` | view |
| `registerPool((address,address,uint24,int24,address),address,address,uint16,(address,uint16,uint16,uint16,uint16,uint16))` | `0x302511dd` | nonpayable |
| `renounceOwnership()` | `0x715018a6` | pure |
| `rescuePoolFees(bytes32)` | `0x5cbe8117` | nonpayable |
| `setCreatorFeeRecipient(bytes32,address)` | `0xed8ef7a3` | nonpayable |
| `setFactory(address)` | `0x5bb47808` | nonpayable |
| `setFeeSweepOperator(address)` | `0x54faf9c3` | nonpayable |
| `setHookFeeBps(uint256)` | `0xbfe7af83` | nonpayable |
| `setMaxInternalPriceImpactBps(uint256)` | `0xb89eddab` | nonpayable |
| `setProtocolFeeRecipient(address)` | `0xe521cb92` | nonpayable |
| `setProtocolFeeShareBps(uint256)` | `0xfc75e481` | nonpayable |
| `setReferralDiscountBps(uint256)` | `0x98da62d5` | nonpayable |
| `setReferralRegistry(address)` | `0x6a79115f` | nonpayable |
| `setReferralShareBps(uint256)` | `0xd07e995b` | nonpayable |
| `transferOwnership(address)` | `0xf2fde38b` | nonpayable |
| `unlockCallback(bytes)` | `0x91dd7346` | nonpayable |


### Events

| Event | topic0 |
|---|---|
| `CreatorFeeRecipientUpdated(bytes32,address,address)` | `0xb45e6b72a7de9a2077babe9717744436f3880e114099956ca85f91a77469a532` |
| `FactorySet(address)` | `0x1edf3afd4ac789736e00d216cd88be164ddcef26a6eedcc30cdb0cb62f3741b1` |
| `FeeSweepOperatorUpdated(address)` | `0xae994ca926e252e299c3df7516cb609272a57bf80b0e0715297e55939f873420` |
| `HookFeeBpsUpdated(uint256)` | `0xaea8b8d37d8110dd00c418d9c1c268f0fbadacb802c284b71a1777e411cd965a` |
| `HookFeeCollected(bytes32,address,uint256,uint256)` | `0xc532c43b3423e14ef72748f1c8291238829ca0af8ba9b67975ad1483485a4b4d` |
| `MaxInternalPriceImpactUpdated(uint256)` | `0x6968b68c1fb468c8b257b012290bf803a6a6d7e79468e0326050724f7573cf01` |
| `OwnershipTransferred(address,address)` | `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` |
| `OwnershipTransferStarted(address,address)` | `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` |
| `PoolConversionSkipped(bytes32,uint256)` | `0xeed2d18eb96f3c2cb8c7b6993512a506c170e17d29355f2d7a0d5961f338de09` |
| `PoolFeesRescued(bytes32,address,uint256,uint256)` | `0x0fbb28f9c335f55dcc5cc19e595ab55f9e6a0fd1b58ad77be3a98f99901daaff` |
| `PoolFeesSwept(bytes32,uint256,uint256)` | `0x2b33b68d948eb789fd57906bde3dc24d9f748c1df9b98d7359910f6aa1c06e2f` |
| `PoolRegistered(bytes32,address,address,address)` | `0x01bf263a1db1652580721573296e1a1fa70b3d4c87f61d02a69c4e1109d2d573` |
| `ProtocolFeeRecipientUpdated(address)` | `0xc1b5345cce283376356748dc57f2dfa7120431d016fc7ca9ba641bc65f91411d` |
| `ProtocolFeeShareUpdated(uint256)` | `0x4d1fc9430e27afb14db15169fd1c79e8b51773302919ac8c049f1c41995e380b` |
| `ReferralDiscountUpdated(uint256)` | `0xe0f45d08835a6839e8d2327d73ee817a6da7276c4776e77abe76eaa524bc92ef` |
| `ReferralFeeAccrued(bytes32,address,address,uint256)` | `0x7ca75a36687fd0a9628cbb8d737989015c0e5236d128a986b078ed14a030fe81` |
| `ReferralFeeClaimed(address,address,uint256)` | `0x646dbd2d0dbd68fc66a49d8c448dd995f308238033d47b3c6122f637b331bfdb` |
| `ReferralRegistrySet(address)` | `0xcf7381fd801bfc0e3e6a57a711e8165131a80c69051919ee96c9896cd87c0c11` |
| `ReferralShareUpdated(uint256)` | `0x7c13f976b8efb8331f00ce07146b8270d065e3789f2eabeab837c72ca942ad61` |


### Errors

| Error | Selector |
|---|---|
| `AlreadyRegistered()` | `0x3a81d6fc` |
| `AlreadySet()` | `0xa741a045` |
| `HookNotImplemented()` | `0x0a85dc29` |
| `InexactQuoteTransfer(address,uint256,uint256)` | `0x197001d6` |
| `InternalSwapRequiresOperator()` | `0x31cdb504` |
| `InvalidBps()` | `0xc6cc5d7f` |
| `InvalidPoolKey()` | `0xc256622b` |
| `MinimumOutputRequired()` | `0x3672d25f` |
| `NotFactory()` | `0x32cc7236` |
| `NotFeeSweepOperator()` | `0x8d42130c` |
| `NothingToRescue()` | `0x00f6b210` |
| `NotPoolManager()` | `0xae18210a` |
| `OwnableInvalidOwner(address)` | `0x1e4fbdf7` |
| `OwnableUnauthorizedAccount(address)` | `0x118cdaa7` |
| `OwnershipCannotBeRenounced()` | `0x2fab92ca` |
| `ReentrancyGuardReentrantCall()` | `0x3ee5aeb5` |
| `SafeCastOverflowedIntToUint(int256)` | `0xa8ce4432` |
| `SafeCastOverflowedUintToInt(uint256)` | `0x24775e06` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `SlippageExceeded(uint256,uint256)` | `0x71c4efed` |
| `UnknownPool()` | `0xf7139e33` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2FeeEscrow

`0xcecCFebAcaDCd9404Ae70b160305Af07D9760A46`


### Functions an application calls

### `balanceOf(address)`

`0x70a08231` · `view` · view

Returns the claimable native ETH balance for `recipient`.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `recipient` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `uint256` |  |

### `balanceOfToken(address,address)`

`0xf59e38b7` · `view` · view

Returns the claimable balance of `token` for `recipient`.

`(account, token)`. Read this rather than an indexer if you want on-chain truth for a claim button.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `recipient` | `address` |  |
| `token` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `arg0` | `uint256` |  |

### `claim()`

`0x4e71d92d` · `nonpayable` · Pull-only, `msg.sender`.

Pays out the caller's entire claimable native ETH balance.

Native-asset balance. Unreachable unless a launch quotes in the native asset, which no approved pair token does.


**Returns**

| Name | Type | Description |
|---|---|---|
| `amount` | `uint256` |  |

### `claimToken(address)`

`0x32f289cf` · `nonpayable` · Pull-only — claims the balance of `msg.sender`. You cannot claim for someone else.

Pays out the caller's entire claimable balance of `token`.

The escrow holds ONE balance per (recipient, token). It does not distinguish creator fees from referral fees — that split is attribution derived off-chain from events — so this withdraws both at once. Fees on Arc are the 6-decimal USDC ERC-20, so this is the path, not the native `claim()`.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `amount` | `uint256` |  |


**Reverts**

- `NoBalance` — nothing accrued for you in that token


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `claim(uint256)` | `0x379607f5` | nonpayable |
| `claimToken(address,uint256)` | `0x1698755f` | nonpayable |
| `credit(address)` | `0xd5d44d80` | payable |
| `creditToken(address,address,uint256)` | `0x09ad4dd9` | nonpayable |


### Events

| Event | topic0 |
|---|---|
| `Claimed(address,uint256)` | `0xd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a` |
| `ClaimedToken(address,address,uint256)` | `0xdbc1ea3a8459e4c7e11fb385b52bbb5cc8c8ab85eec5d883ac9aa78c171f5141` |
| `Credited(address,address,uint256)` | `0x4e45da441832cf53bdaa69235704fc0575e68210f459ee1562911024b12967d5` |
| `CreditedToken(address,address,address,uint256)` | `0x5d104c62f50449fadfe6f4013c8f36588d32737f94b5ac9b83ddad33b3e1ffdf` |


### Errors

| Error | Selector |
|---|---|
| `InsufficientBalance(uint256,uint256)` | `0xcf479181` |
| `NoBalance()` | `0xc2caa2a6` |
| `ReentrancyGuardReentrantCall()` | `0x3ee5aeb5` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `TransferFailed()` | `0x90b8ec18` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2ReferralRegistry

`0xEB286974C35d2741B0fe9b2a1Cd41E53d06aE406`


### Functions an application calls

### `referrerOf(address)`

`0xd21cacdf` · `view` · view

The permanent referrer of each user, or the zero address if they have never been referred. Read by every curve on every trade.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `user` | `address` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `referrer` | `address` |  |

### `setReferrer(address)`

`0xa18a7bfc` · `nonpayable` · Self-service — binds `msg.sender`.

Claims a referrer for the caller before their first trade.

Reverts rather than no-ops on an existing binding: someone calling this directly asked for a specific outcome and should be told it did not happen, where a trade merely carrying a stale referrer should still settle.

Permanent and never rewritten. Bind before trading, or pass the referrer to `buy` instead.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `referrer` | `address` |  |


**Reverts**

- `AlreadyReferred`
- `SelfReferral`
- `ReciprocalReferral`
- `ZeroAddress`


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `bindFor(address,address)` | `0x620e206c` | nonpayable |
| `factory()` | `0xc45a0155` | view |
| `memeHook()` | `0x6651812c` | view |


### Events

| Event | topic0 |
|---|---|
| `ReferrerBound(address,address,address)` | `0x5b6dcb011725a9616ecced5408efb270f5e20477283b63e06c8b4eb0b4da4296` |


### Errors

| Error | Selector |
|---|---|
| `AlreadyReferred()` | `0x7aabdfe3` |
| `NotAuthorizedBinder()` | `0xbe447ef2` |
| `ReciprocalReferral()` | `0xb6ea0b01` |
| `SelfReferral()` | `0x55e8f70e` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2LaunchLocker

`0xe047D0F0ce0dD600732793762B1f1929Adc5015d`


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `acceptOwnership()` | `0x79ba5097` | nonpayable |
| `factory()` | `0xc45a0155` | view |
| `isLocked(address)` | `0x4a4fbeec` | view |
| `lockedPositions(address)` | `0xfa22143d` | view |
| `lockedTokenSupply(address)` | `0x732e78e4` | view |
| `lockPosition(address,uint256)` | `0x292d5732` | nonpayable |
| `lockTokenSupply(address,uint256)` | `0xb8a0d7ab` | nonpayable |
| `onERC721Received(address,address,uint256,bytes)` | `0x150b7a02` | view |
| `owner()` | `0x8da5cb5b` | view |
| `pendingOwner()` | `0xe30c3978` | view |
| `positionManager()` | `0x791b98bc` | view |
| `renounceOwnership()` | `0x715018a6` | pure |
| `setFactory(address)` | `0x5bb47808` | nonpayable |
| `transferOwnership(address)` | `0xf2fde38b` | nonpayable |


### Events

| Event | topic0 |
|---|---|
| `FactorySet(address)` | `0x1edf3afd4ac789736e00d216cd88be164ddcef26a6eedcc30cdb0cb62f3741b1` |
| `OwnershipTransferred(address,address)` | `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` |
| `OwnershipTransferStarted(address,address)` | `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` |
| `PositionLocked(address,uint256)` | `0x2cabb2a2973327d5863ceb4707e9441851243897e86d587ee35943599752eb54` |
| `TokenSupplyLocked(address,uint256)` | `0xaf33c4aba92959b3e7ddc83ab728938262da159a6c05ca836f6c46f9bcb2c740` |


### Errors

| Error | Selector |
|---|---|
| `AlreadyInitialized()` | `0x0dc149f0` |
| `NotFactory()` | `0x32cc7236` |
| `NotPositionManager()` | `0x20fdc658` |
| `OwnableInvalidOwner(address)` | `0x1e4fbdf7` |
| `OwnableUnauthorizedAccount(address)` | `0x118cdaa7` |
| `OwnershipCannotBeRenounced()` | `0x2fab92ca` |
| `PositionAlreadyLocked()` | `0xfe3099b6` |
| `PositionNotHeld()` | `0x6b49c94a` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2LaunchDeployer

`0x5C5c202271E1300bD5Ce43A4F5C1cEA8efd57B63`


### Functions an application calls

### `predictLaunchAddresses((address,address,address,address,(address,uint16,uint16,uint16,uint16,uint16),address,uint256,uint256,uint256,uint256,uint256,bytes32,string,string,string,string,(string,string,string,string,string)))`

`0xe6a900b5` · `view` · view

Returns the addresses `deployLaunch` would produce for `params`, without deploying anything.

Lets a caller confirm that a launch it has not seen confirmed yet will land where it expects, and lets the launch path be checked for a salt the creator has already used. The token is derived from the curve because the curve's address is one of the token's constructor arguments, so the pair has to be computed in deployment order.

Computes the CREATE2 token and curve addresses before you send. Use it to mine a vanity address, and to check for an existing deployment — a reused salt reverts with the unhelpful `FailedDeployment`.


**Parameters**

| Name | Type | Description |
|---|---|---|
| `params` | `(address,address,address,address,(address,uint16,uint16,uint16,uint16,uint16),address,uint256,uint256,uint256,uint256,uint256,bytes32,string,string,string,string,(string,string,string,string,string))` |  |


**Returns**

| Name | Type | Description |
|---|---|---|
| `token` | `address` |  |
| `curve` | `address` |  |


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `deployLaunch((address,address,address,address,(address,uint16,uint16,uint16,uint16,uint16),address,uint256,uint256,uint256,uint256,uint256,bytes32,string,string,string,string,(string,string,string,string,string)))` | `0x84b2d5c6` | nonpayable |
| `factory()` | `0xc45a0155` | view |
| `referralRegistry()` | `0x4e627e62` | view |


### Errors

| Error | Selector |
|---|---|
| `Create2EmptyBytecode()` | `0x4ca249dc` |
| `FailedDeployment()` | `0xb06ebf3d` |
| `InsufficientBalance(uint256,uint256)` | `0xcf479181` |
| `MetadataTooLong()` | `0x85b8e2f4` |
| `NotFactory()` | `0x32cc7236` |
| `ZeroAddress()` | `0xd92e233d` |

---
## FociV2GraduationExecutor

`0x02e7d818080bf85EEB7191536A768B0CFdB38D5D`


### Other functions

| Signature | Selector | Mutability |
|---|---|---|
| `factory()` | `0xc45a0155` | view |
| `locker()` | `0xd7b96d4e` | view |
| `mintFullRangePosition(address,(address,address,uint24,int24,address),int24,int24,uint160,uint256,uint256,address,address,address)` | `0xcbba1910` | payable |
| `permit2()` | `0x12261ee7` | view |
| `positionManager()` | `0x791b98bc` | view |


### Events

| Event | topic0 |
|---|---|
| `GraduationDustRetained(address,address,uint256)` | `0x667636bce2491e3f246c8b4ec1f4ca0be227dfa611d0575c59f5949283b433c1` |
| `GraduationDustSwept(address,address,uint256)` | `0x80a5a2ff8b8c5533e5862e4e161bbcade9af6fd9d67bef56a590b062107f027f` |


### Errors

| Error | Selector |
|---|---|
| `FeeTransferFailed()` | `0x4033e4e3` |
| `MintAmountOverflow()` | `0xeee66814` |
| `NotFactory()` | `0x32cc7236` |
| `SafeERC20FailedOperation(address)` | `0x5274afe7` |
| `SlippageExceeded(uint256,uint256)` | `0x71c4efed` |
| `ZeroAddress()` | `0xd92e233d` |
