> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inkyswap.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Token Creation

> createLaunch and createLaunchWithReferral on the InkyPump V2 hook.

Launches happen through two entry points on the InkyPump V2 hook at `0x4cC8F6d5B7cE150CCC0A9B7664532B1283b96AC4`. Use `createLaunch` for a plain launch. Use `createLaunchWithReferral` to record a referral code on chain at creation time.

## createLaunch

```solidity theme={null}
function createLaunch(InkyPumpTypes.CreateLaunchParams calldata params)
    external payable returns (uint256 launchId);
```

`msg.value` is the optional creator prebuy. Send 0 for no prebuy. Send any positive amount to prebuy that much ETH at the curve's starting price in the same transaction.

Returns the new `launchId`. The launch's token address is in the `LaunchCreated` event emitted by the same call.

## createLaunchWithReferral

```solidity theme={null}
function createLaunchWithReferral(
    InkyPumpTypes.CreateLaunchParams calldata params,
    string calldata referralCode
) external payable returns (uint256 launchId);
```

Same behaviour as `createLaunch`, plus a `Referral` event recording the code:

```solidity theme={null}
event Referral(uint256 indexed launchId, address indexed trader, string referralCode);
```

If `referralCode` is empty, this still works but does not emit the `Referral` event. Use the plain `createLaunch` when you do not have a referral code.

## CreateLaunchParams

```solidity theme={null}
struct CreateLaunchParams {
    string name;
    string ticker;
    string description;
    string imageUrl;
    string telegram;           // optional
    string twitter;            // optional
    string website;            // optional
    uint16 creatorFeeSplitBps; // 0 to 10_000
    uint32 gainBps;            // 0 to 200_000 (1x to 21x)
    uint96 targetRaise;        // 1 ether to 5 ether
    uint32 antiSnipeDuration;  // 0, 20, 40, or 60 seconds
    uint64 startTime;          // 0 for immediate, future unix timestamp for scheduled
}
```

### Prebuy

There is no `prebuyEth` field. To prebuy at launch, send the prebuy amount as `msg.value` on the `createLaunch` call. The creator's prebuy executes in the same transaction as the launch, at the curve's starting price, and bypasses the anti-snipe captcha gate.

### Field constraints

| Field                | Constraint                                                 | Reverts if violated |
| -------------------- | ---------------------------------------------------------- | ------------------- |
| `targetRaise`        | Between `MIN_RAISE` (1 ether) and `MAX_RAISE` (5 ether)    | `RaiseOutOfRange`   |
| `gainBps`            | At most `MAX_GAIN_BPS` (200,000)                           | `GainTooHigh`       |
| `creatorFeeSplitBps` | At most `BPS_DENOMINATOR` (10,000)                         | `SplitOutOfRange`   |
| `msg.value`          | 0 (no prebuy) or any positive amount your wallet can cover | none directly       |
| `startTime`          | Either 0 or in the future                                  | `LaunchInPast`      |

### What happens during the call

1. The hook deploys a new ERC20 token with the supplied metadata
2. It computes the sale supply and liquidity supply for the curve through `SaleSplitCalculator(targetRaise, gainBps)`
3. It records the `LaunchConfig` in storage at the new `launchId`
4. It emits `LaunchCreated` and `LaunchMetadata`
5. If `msg.value > 0`, it executes the creator prebuy at the curve's starting price
6. If called as `createLaunchWithReferral` with a non empty code, it emits `Referral`

## Events emitted

```solidity theme={null}
event LaunchCreated(
    uint256 indexed launchId,
    address indexed creator,
    address token,
    uint96 targetRaise
);

event LaunchMetadata(
    uint256 indexed launchId,
    string name,
    string ticker,
    string description,
    string imageUrl,
    string telegram,
    string twitter,
    string website
);

event SalePortionResolved(
    uint256 indexed launchId,
    uint16 salePortionBps,
    uint256 marginalPrice,
    uint256 poolPrice
);
```

If `msg.value > 0`, a `Trade` event also fires for the prebuy.

## Example: minimal launch

```javascript theme={null}
import { encodeFunctionData, parseEther } from "viem"

const params = {
  name: "My Token",
  ticker: "MINE",
  description: "Launching on InkyPump V2",
  imageUrl: "https://example.com/logo.png",
  telegram: "",
  twitter: "",
  website: "",
  creatorFeeSplitBps: 7000,     // 70 percent of variable fee to creator
  gainBps: 50_000,              // 6x gain
  targetRaise: parseEther("3"),
  antiSnipeDuration: 40,        // 40 second captcha gate
  startTime: 0n,
}
// To prebuy, send ETH with the transaction (set `value` on the tx call below).

const data = encodeFunctionData({
  abi: INKY_PUMP_HOOK_ABI,
  functionName: "createLaunch",
  args: [params],
})

const hash = await wallet.sendTransaction({
  to: "0x4cC8F6d5B7cE150CCC0A9B7664532B1283b96AC4",
  data,
  value: 0n,
})
```

## Common errors

| Revert            | Cause                                                           |
| ----------------- | --------------------------------------------------------------- |
| `RaiseOutOfRange` | `targetRaise` is below 1 ether or above 5 ether                 |
| `GainTooHigh`     | `gainBps` exceeds 200,000                                       |
| Tx out of funds   | Wallet does not have enough ETH for gas plus `msg.value` prebuy |
| `LaunchInPast`    | `startTime` is in the past and not zero                         |
| `SplitOutOfRange` | `creatorFeeSplitBps` is above 10,000                            |
