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

# Buy & Sell

> Trading tokens on the KasFun bonding curve

<Info>
  The code examples on this page use a `bondingCurve` contract instance for price quotes. Get its address from `MemeFactory.bondingCurve()`. See [Contract Overview](/contracts/overview) for details.
</Info>

## Buy Tokens

Send KAS to `MemeFactory.buy()` to receive tokens.

```solidity theme={null}
function buy(address token, uint256 minTokensOut) external payable;
```

| Parameter      | Description                                     |
| -------------- | ----------------------------------------------- |
| `token`        | Token contract address                          |
| `minTokensOut` | Minimum tokens to receive (slippage protection) |
| `msg.value`    | Amount of KAS to spend (wei)                    |

<CodeGroup>
  ```javascript ethers.js theme={null}
  const kasAmount = ethers.parseEther("100"); // 100 KAS

  // 1. Get quote first
  const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
    kasAmount, tokenReserves, kasReserves, vToken, vKas
  );

  // 2. Apply slippage (e.g., 20%)
  const minTokensOut = tokensOut * 80n / 100n;

  // 3. Execute buy
  const tx = await factory.buy(tokenAddress, minTokensOut, {
    value: kasAmount,
  });
  await tx.wait();
  ```
</CodeGroup>

### Buy Event

```solidity theme={null}
event Buy(
    address indexed token,
    address indexed buyer,
    uint256 kasAmount,
    uint256 tokenAmount,
    uint256 fee
);
```

## Sell Tokens

Sell tokens back for KAS via `MemeFactory.sell()`.

```solidity theme={null}
function sell(address token, uint256 tokenAmount, uint256 minKasOut) external;
```

| Parameter     | Description                                  |
| ------------- | -------------------------------------------- |
| `token`       | Token contract address                       |
| `tokenAmount` | Amount of tokens to sell (wei)               |
| `minKasOut`   | Minimum KAS to receive (slippage protection) |

<Warning>
  Before selling, you must **approve** the MemeFactory contract to spend your tokens.
</Warning>

<CodeGroup>
  ```javascript ethers.js theme={null}
  const tokenAmount = ethers.parseEther("1000000"); // 1M tokens

  // 1. Approve MemeFactory to spend tokens
  const tokenContract = new ethers.Contract(tokenAddress, [
    "function approve(address spender, uint256 amount) returns (bool)",
  ], signer);
  const approveTx = await tokenContract.approve(FACTORY_ADDRESS, tokenAmount);
  await approveTx.wait();

  // 2. Get quote
  const kasOut = await bondingCurve.calculateSellReturnWithParams(
    tokenAmount, tokenReserves, kasReserves, vToken, vKas
  );

  // 3. Apply slippage (e.g., 20%)
  const minKasOut = kasOut * 80n / 100n;

  // 4. Execute sell
  const tx = await factory.sell(tokenAddress, tokenAmount, minKasOut);
  await tx.wait();
  ```
</CodeGroup>

### Sell Event

```solidity theme={null}
event Sell(
    address indexed token,
    address indexed seller,
    uint256 tokenAmount,
    uint256 kasAmount,
    uint256 fee
);
```

## Slippage Protection

Always set `minTokensOut` (buy) or `minKasOut` (sell) to protect against price changes between quoting and execution.

| Slippage | Multiplier         | Use Case                       |
| -------- | ------------------ | ------------------------------ |
| 5%       | `quote * 95 / 100` | Low volatility                 |
| 20%      | `quote * 80 / 100` | Normal (recommended)           |
| 50%      | `quote * 50 / 100` | High volatility / large orders |

<Tip>
  KasFun website uses 20% default slippage. For programmatic trading, adjust based on the token's volatility and your order size relative to pool reserves.
</Tip>

## Complete Trading Flow

```javascript theme={null}
import { ethers } from "ethers";

const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

const FACTORY = "0x..."; // MemeFactory Contract Address

const factory = new ethers.Contract(FACTORY, [
  "function buy(address token, uint256 minTokensOut) payable",
  "function sell(address token, uint256 tokenAmount, uint256 minKasOut)",
  "function getTokenInfo(address token) view returns (tuple(uint256 tokenId, address creator, address pool, uint256 tokenReserves, uint256 kasReserves, uint256 createdAt, bool fulfilled, bool graduated, string metadataUri, uint256 paramVersion))",
  "function getTokenParamVersion(address token) view returns (tuple(uint256 graduationThreshold, uint256 virtualToken, uint256 virtualKas, uint160 sqrtPriceX96Token0, uint160 sqrtPriceX96Token1, bool active))",
  "function bondingCurve() view returns (address)",
], signer);

// Get BondingCurve address
const bcAddress = await factory.bondingCurve();
const bc = new ethers.Contract(bcAddress, [
  "function calculateBuyReturnWithParams(uint256,uint256,uint256,uint256,uint256) pure returns (uint256)",
  "function calculateSellReturnWithParams(uint256,uint256,uint256,uint256,uint256) pure returns (uint256)",
], provider);

const TOKEN = "0x..."; // your token address

// Read current state
const info = await factory.getTokenInfo(TOKEN);
const params = await factory.getTokenParamVersion(TOKEN);

// --- BUY ---
const kasIn = ethers.parseEther("100");
const buyReturn = await bc.calculateBuyReturnWithParams(
  kasIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
const minTokens = buyReturn * 80n / 100n; // 20% slippage
const buyTx = await factory.buy(TOKEN, minTokens, { value: kasIn });
await buyTx.wait();

// --- SELL ---
const tokensIn = ethers.parseEther("500000");
const sellReturn = await bc.calculateSellReturnWithParams(
  tokensIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
const minKas = sellReturn * 80n / 100n; // 20% slippage

// Approve first
const token = new ethers.Contract(TOKEN, [
  "function approve(address,uint256) returns (bool)",
], signer);
await (await token.approve(FACTORY, tokensIn)).wait();

const sellTx = await factory.sell(TOKEN, tokensIn, minKas);
await sellTx.wait();
```

<Note>
  Bonding curve trading is only available when the token is not yet fulfilled (`info.fulfilled === false`). Once fulfilled, buy/sell will revert.
</Note>
