> ## 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.

# 价格计算

> 理解 Bonding Curve 数学原理

<Info>
  BondingCurve 合约地址可通过 `MemeFactory.bondingCurve()` 获取。详见[合约概览](/zh/contracts/overview)。
</Info>

## 恒定乘积公式

KasFun 使用**恒定乘积** Bonding Curve（类似 Uniswap V2），并引入**虚拟储备**：

```
(tokenReserves + virtualToken) * (kasReserves + virtualKas) = k
```

虚拟储备设定初始价格和曲线形状，无需种子流动性。

## 获取曲线参数

计算价格前，先获取代币的当前状态和曲线参数：

```javascript theme={null}
// 1. 当前储备
const info = await factory.getTokenInfo(tokenAddress);
const { tokenReserves, kasReserves } = info;

// 2. 虚拟参数
const params = await factory.getTokenParamVersion(tokenAddress);
const { virtualToken, virtualKas, graduationThreshold } = params;
```

## 价格计算函数

BondingCurve 合约提供三个纯计算函数：

### 计算买入收益

给定 KAS 数量，能得到多少代币？

```solidity theme={null}
function calculateBuyReturnWithParams(
    uint256 kasIn,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 tokensOut)
```

```javascript theme={null}
const kasIn = ethers.parseEther("100"); // 100 KAS
const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
  kasIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("可得代币:", ethers.formatEther(tokensOut));
```

### 计算卖出收益

卖出一定数量的代币，能得到多少 KAS？

```solidity theme={null}
function calculateSellReturnWithParams(
    uint256 tokensIn,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 kasOut)
```

```javascript theme={null}
const tokensIn = ethers.parseEther("1000000"); // 100 万代币
const kasOut = await bondingCurve.calculateSellReturnWithParams(
  tokensIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("可得 KAS:", ethers.formatEther(kasOut));
```

### 计算买入成本

要得到指定数量的代币，需要花费多少 KAS？

```solidity theme={null}
function calculateBuyCostWithParams(
    uint256 tokensOut,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 kasIn)
```

```javascript theme={null}
const desiredTokens = ethers.parseEther("1000000"); // 想要 100 万代币
const kasNeeded = await bondingCurve.calculateBuyCostWithParams(
  desiredTokens,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("需要 KAS:", ethers.formatEther(kasNeeded));
```

## 当前价格

获取代币当前价格（每个代币对应的 KAS）：

```javascript theme={null}
// 通过 MemeFactory（便捷方式）
const price = await factory.getCurrentPrice(tokenAddress);

// 通过 BondingCurve（从储备计算）
const price = await bondingCurve.getCurrentPrice(
  info.tokenReserves,
  info.kasReserves
);

console.log("价格:", ethers.formatEther(price), "KAS/token");
```

## 价格影响

对于大额交易，价格影响可能很大。通过比较有效价格和当前价格来计算：

```javascript theme={null}
const kasIn = ethers.parseEther("1000"); // 1000 KAS
const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
  kasIn, tokenReserves, kasReserves, vToken, vKas
);

const effectivePrice = kasIn * BigInt(1e18) / tokensOut; // 每代币 KAS
const currentPrice = await factory.getCurrentPrice(tokenAddress);
const priceImpact = Number(effectivePrice - currentPrice) / Number(currentPrice) * 100;

console.log(`价格影响: ${priceImpact.toFixed(2)}%`);
```

<Tip>
  当 `kasIn` 相对于 `kasReserves` 很小时，价格影响趋近于零，有效价格趋近于现货价格。
</Tip>

## 毕业阈值

每个代币的曲线参数中包含 `graduationThreshold`。当 `kasReserves >= graduationThreshold` 时，代币毕业：

```javascript theme={null}
const params = await factory.getTokenParamVersion(tokenAddress);
const info = await factory.getTokenInfo(tokenAddress);

const remaining = params.graduationThreshold - info.kasReserves;
console.log("距毕业还需:", ethers.formatEther(remaining), "KAS");
```
