Skip to main content
The code examples on this page use a bondingCurve contract instance for price quotes. Get its address from MemeFactory.bondingCurve(). See Contract Overview for details.

Buy Tokens

Send KAS to MemeFactory.buy() to receive tokens.
function buy(address token, uint256 minTokensOut) external payable;
ParameterDescription
tokenToken contract address
minTokensOutMinimum tokens to receive (slippage protection)
msg.valueAmount of KAS to spend (wei)
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();

Buy Event

event Buy(
    address indexed token,
    address indexed buyer,
    uint256 kasAmount,
    uint256 tokenAmount,
    uint256 fee
);

Sell Tokens

Sell tokens back for KAS via MemeFactory.sell().
function sell(address token, uint256 tokenAmount, uint256 minKasOut) external;
ParameterDescription
tokenToken contract address
tokenAmountAmount of tokens to sell (wei)
minKasOutMinimum KAS to receive (slippage protection)
Before selling, you must approve the MemeFactory contract to spend your tokens.
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();

Sell Event

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.
SlippageMultiplierUse Case
5%quote * 95 / 100Low volatility
20%quote * 80 / 100Normal (recommended)
50%quote * 50 / 100High volatility / large orders
KasFun website uses 20% default slippage. For programmatic trading, adjust based on the token’s volatility and your order size relative to pool reserves.

Complete Trading Flow

import { ethers } from "ethers";

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

const FACTORY = "0x5F65Df9DCf7d764CA9d319Baf89611d289546A81";

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();
Bonding curve trading is only available when the token has not graduated (info.fulfilled === false). Once fulfilled, buy/sell will revert.