# Create Token Guide

## Overview

This guide walks you through the complete flow of creating a new token on the Bullshot Protocol — from reading fee parameters to calling `createToken` on-chain.

---

## Flow Summary

| Step | Action | Description |
|------|--------|-------------|
| 1 | Read fee params | Fetch `creationFeeAmount`, `buyFeePercent`, `FEE_DENOMINATOR` from BullshotFactory |
| 2 | Calculate `msg.value` | `initAmountIn + buyFee + creationFee` |
| 3 | Call `createToken` | Deploy a new BCToken + BondingCurve pair |
| 4 | Listen for `Created` event | Get the new token and bonding curve addresses |
| 5 | (Optional) Buy more tokens | Call `bondingCurve.buy()` with additional BNB |

---

## Step 1 — Read Fee Parameters

```javascript
const factory = new ethers.Contract(FACTORY_ADDRESS, BullshotFactoryABI, provider);

const creationFeeAmount = await factory.creationFeeAmount(); // 150000000000000 wei = 0.00015 BNB
const buyFeePercent     = await factory.buyFeePercent();     // 10 = 1%
const FEE_DENOMINATOR   = 1000;
```

> **Current live values:**
> - `FEE_DENOMINATOR` = **1000**
> - `buyFeePercent` = **10** → 1% buy fee
> - `sellFeePercent` = **10** → 1% sell fee
> - `creationFeeAmount` = **150000000000000 wei** (0.00015 BNB)

---

## Step 2 — Calculate msg.value

### Without initial buy

```javascript
const initAmountIn = ethers.constants.Zero;
const msgValue = creationFeeAmount; // just the creation fee
```

### With initial buy (e.g. 0.5 BNB)

```javascript
const initAmountIn = ethers.utils.parseEther("0.5");
const buyFee = initAmountIn.mul(buyFeePercent).div(FEE_DENOMINATOR);
const msgValue = initAmountIn.add(buyFee).add(creationFeeAmount);
```

**Formula:**
```
msg.value = initAmountIn
          + (initAmountIn × buyFeePercent / FEE_DENOMINATOR)
          + creationFeeAmount
```

---

## Step 3 — Call createToken

```solidity
function createToken(
    string memory name,
    string memory ticker,
    uint256 initAmountIn
) external payable
```

```javascript
const signer = provider.getSigner();
const factory = new ethers.Contract(FACTORY_ADDRESS, BullshotFactoryABI, signer);

const tx = await factory.createToken(
    "Bullshot",   // token name
    "BULL",       // ticker symbol
    initAmountIn, // BNB to spend on initial buy (0 = skip)
    { value: msgValue }
);

const receipt = await tx.wait();
```

---

## Step 4 — Get token and bonding curve addresses from the Created event

```javascript
// Parse the Created event from the receipt
const iface = new ethers.utils.Interface(BullshotFactoryABI);

let bondingCurveAddress, tokenAddress;
for (const log of receipt.logs) {
    try {
        const parsed = iface.parseLog(log);
        if (parsed.name === "Created") {
            bondingCurveAddress = parsed.args.bondingCurve;
            tokenAddress        = parsed.args.token;
            console.log("BondingCurve:", bondingCurveAddress);
            console.log("Token:", tokenAddress);
        }
    } catch (_) {}
}
```

---

## Step 5 — (Optional) Buy Additional Tokens

After token creation, the bonding curve is live and ready for trading.

```javascript
const bondingCurve = new ethers.Contract(bondingCurveAddress, BondingCurveABI, signer);

const additionalBuy = ethers.utils.parseEther("0.1"); // 0.1 BNB
const additionalFee = additionalBuy.mul(buyFeePercent).div(FEE_DENOMINATOR);
const buyMsgValue   = additionalBuy.add(additionalFee);

// Pre-calculate expected output
const [expectedOut] = await bondingCurve.calcBuyExactIn(additionalBuy);
const minOut = expectedOut.mul(95).div(100); // 5% slippage

const deadline = Math.floor(Date.now() / 1000) + 60;

const buyTx = await bondingCurve.buy(
    additionalBuy,
    minOut,
    signerAddress,
    deadline,
    { value: buyMsgValue }
);
await buyTx.wait();
```

---

## Parameter Reference

### createToken Parameters

| Parameter | Type | Description | Example |
|-----------|------|-------------|---------|
| `name` | `string` | Full token name | `"Bullshot"` |
| `ticker` | `string` | Token symbol / ticker | `"BULL"` |
| `initAmountIn` | `uint256` | BNB to spend on initial buy (excluding fee). Pass `0` to skip | `ethers.utils.parseEther("0.5")` |
| `msg.value` | `uint256` | Must equal `initAmountIn + buyFee + creationFeeAmount` | Calculated above |

### Fixed Protocol Parameters (Set by owner, cannot be changed by creator)

| Parameter | Description |
|-----------|-------------|
| `totalSupply` | Always 1,000,000,000 tokens (18 decimals) |
| `tokenReserve` | 800M tokens available for sale on bonding curve |
| `lpTokens` | 200M tokens reserved for PancakeSwap LP at launch |
| `launchThreshold` | ~24 BNB collected triggers DEX migration |
| `virtualEthReserve` (initial) | 6 BNB (sets starting price) |

---

## Complete Example (JavaScript / ethers.js v5)

```javascript
const { ethers } = require("ethers");
const BullshotFactoryABI = require("./BullshotFactory.abi.json");
const BondingCurveABI    = require("./BondingCurve.abi.json");

const FACTORY_ADDRESS = "0x..."; // deployed BullshotFactory address
const RPC_URL = "https://bsc-dataseed.binance.org/";

async function createToken(privateKey, name, ticker, initBnbAmount) {
    const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
    const signer   = new ethers.Wallet(privateKey, provider);
    const factory  = new ethers.Contract(FACTORY_ADDRESS, BullshotFactoryABI, signer);

    // Read fee params
    const creationFeeAmount = await factory.creationFeeAmount();
    const buyFeePercent     = await factory.buyFeePercent();
    const FEE_DENOMINATOR   = 1000;

    // Calculate msg.value
    const initAmountIn = ethers.utils.parseEther(initBnbAmount.toString());
    const buyFee       = initAmountIn.mul(buyFeePercent).div(FEE_DENOMINATOR);
    const msgValue     = initAmountIn.add(buyFee).add(creationFeeAmount);

    console.log(`Creating token "${name}" (${ticker})`);
    console.log(`Initial buy: ${initBnbAmount} BNB`);
    console.log(`Total msg.value: ${ethers.utils.formatEther(msgValue)} BNB`);

    // Send transaction
    const tx      = await factory.createToken(name, ticker, initAmountIn, { value: msgValue });
    const receipt = await tx.wait();

    // Parse Created event
    const iface = new ethers.utils.Interface(BullshotFactoryABI);
    for (const log of receipt.logs) {
        try {
            const parsed = iface.parseLog(log);
            if (parsed.name === "Created") {
                console.log("\nToken created successfully!");
                console.log("BondingCurve:", parsed.args.bondingCurve);
                console.log("Token:", parsed.args.token);
                console.log("Creator:", parsed.args.creator);
                return {
                    bondingCurve: parsed.args.bondingCurve,
                    token: parsed.args.token
                };
            }
        } catch (_) {}
    }
}

// Example: Create "Bullshot" token with 0.5 BNB initial buy
createToken(process.env.PRIVATE_KEY, "Bullshot", "BULL", 0.5);
```

---

## Notes

1. **Wrong value error**: If `msg.value` doesn't match the formula exactly, the transaction reverts with `"Wrong value"`. Always read fee params on-chain before sending.
2. **Gas**: Token creation involves deploying two ERC1167 proxies and optionally executing a buy. Estimate gas before sending.
3. **Pair address**: The `pair` field in the `Created` event is always `address(0)`. The actual PancakeSwap pair is created lazily on the first post-creation buy.
4. **Name and ticker**: These are free-form strings. No validation is performed on-chain. Choose wisely.
5. **Immediate buy**: Setting `initAmountIn > 0` performs an initial buy in the same transaction as token creation — the creator gets the first tokens at the lowest price.
