PumpFun智能合约系统原理
1. 虚拟储备定价机制
PumpFun采用创新的虚拟储备定价机制,这是一种基于Uniswap V2改进的AMM(自动做市商)模型:
-
双重储备系统
- 虚拟储备:用于价格计算和市场调控
- 实际储备:记录实际的代币和ETH持有量
-
价格计算公式
// 价格计算的核心逻辑 uint256 pricePerToken = virtualTokenReserves - tokenAmount; uint256 totalLiquidity = virtualEthReserves * virtualTokenReserves; uint256 newEthReserves = totalLiquidity/pricePerToken; uint256 ethCost = newEthReserves - virtualEthReserves;
-
初始参数设置
- 初始虚拟代币储备:10^27
- 初始虚拟ETH储备:3*10^21
- 代币总供应量:10^27
- 市值上限:10^23
2. 代币发行机制
-
代币创建流程
用户调用 -> TokenFactory.deployERC20Token() ├── 创建ERC20代币 ├── 记录代币信息 ├── 授权PumpFun合约 └── 自动创建交易池
-
初始化参数
- 固定初始供应量:10^27
- 自动创建交易池
- 预设市值上限
3. 交易机制
-
买入机制
- 检查剩余代币比例(>20%)
- 计算ETH成本
- 收取手续费
- 更新储备状态
- 检查完成条件
-
卖出机制
- 验证交易状态
- 计算ETH返还
- 收取手续费
- 更新储备状态
-
完成条件
- 市值超过上限
- 剩余代币比例低于20%
4. 费用系统
-
创建费用
- 创建池子时一次性收取
- 可配置费用金额
-
交易手续费
- 基于交易金额的百分比
- 使用基点计算(1 basis point = 0.01%)
- 费用接收地址可配置
EVM PumpFun智能合约系统源码分析
合约源码及注释
1. PumpFun.sol
// SPDX-License-Identifier: MIT // 指定开源协议为MIT
pragma solidity ^0.8.24; // 指定Solidity编译器版本
// 导入OpenZeppelin的防重入和ERC20接口合约
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// 定义Uniswap V2工厂接口
interface IUniswapV2Factory {
// 创建交易对的函数
function createPair(
address tokenA, // 代币A地址
address tokenB // 代币B地址
) external returns (address pair); // 返回创建的交易对地址
}
// 定义Uniswap V2路由接口
interface IUniswapV2Router02 {
// 代币换ETH的函数,支持收取转账手续费
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn, // 输入代币数量
uint amountOutMin, // 最小输出ETH数量
address[] calldata path, // 交易路径
address to, // 接收地址
uint deadline // 截止时间
) external;
// 获取工厂合约地址
function factory() external pure returns (address);
// 获取WETH合约地址
function WETH() external pure returns (address);
// 添加ETH流动性的函数
function addLiquidityETH(
address token, // 代币地址
uint amountTokenDesired, // 期望添加的代币数量
uint amountTokenMin, // 最小代币数量
uint amountETHMin, // 最小ETH数量
address to, // 接收LP代币的地址
uint deadline // 截止时间
)
external
payable
returns (
uint amountToken, // 实际添加的代币数量
uint amountETH, // 实际添加的ETH数量
uint liquidity // 获得的LP代币数量
);
}
// PumpFun主合约,继承防重入保护
contract PumpFun is ReentrancyGuard {
// 允许合约接收ETH
receive() external payable {}
// 状态变量声明
address private owner; // 合约拥有者地址
address private feeRecipient; // 手续费接收地址
uint256 private initialVirtualTokenReserves; // 初始虚拟代币储备
uint256 private initialVirtualEthReserves; // 初始虚拟ETH储备
uint256 private tokenTotalSupply; // 代币总供应量
uint256 private mcapLimit; // 市值上限
uint256 private feeBasisPoint; // 手续费基点
uint256 private createFee; // 创建池子费用
IUniswapV2Router02 private uniswapV2Router; // Uniswap路由器实例
// 用户信息结构体
struct Profile {
address user; // 用户地址
Token[] tokens; // 用户的代币列表
}
// 代币信息结构体
struct Token {
address tokenMint; // 代币合约地址
uint256 virtualTokenReserves; // 虚拟代币储备
uint256 virtualEthReserves; // 虚拟ETH储备
uint256 realTokenReserves; // 实际代币储备
uint256 realEthReserves; // 实际ETH储备
uint256 tokenTotalSupply; // 代币总供应量
uint256 mcapLimit; // 市值上限
bool complete; // 是否完成标志
}
// 代币曲线映射,key为代币地址,value为Token结构体
mapping (address => Token) public bondingCurve;
// 事件定义
event CreatePool(address indexed mint, address indexed user); // 创建池子事件
event Complete(address indexed user, address indexed mint, uint256 timestamp); // 完成事件
event Trade( // 交易事件
address indexed mint, // 代币地址
uint256 ethAmount, // ETH数量
uint256 tokenAmount, // 代币数量
bool isBuy, // 是否为买入
address indexed user, // 用户地址
uint256 timestamp, // 时间戳
uint256 virtualEthReserves, // 虚拟ETH储备
uint256 virtualTokenReserves // 虚拟代币储备
);
// 仅所有者修饰符
modifier onlyOwner {
require(msg.sender == owner, "Not Owner");
_;
}
// 构造函数
constructor(
address newAddr, // 新的手续费接收地址
uint256 feeAmt, // 创建池子费用
uint256 basisFee // 基础手续费率
){
feeRecipient = newAddr;
createFee = feeAmt;
feeBasisPoint = basisFee;
initialVirtualTokenReserves = 10**27; // 设置初始虚拟代币储备
initialVirtualEthReserves = 3*10**21; // 设置初始虚拟ETH储备
tokenTotalSupply = 10**27; // 设置代币总供应量
mcapLimit = 10**23; // 设置市值上限
}
// 创建交易池函数
function createPool(
address token, // 代币地址
uint256 amount // 代币数量
) payable public {
require(amount > 0, "CreatePool: Larger than Zero");
require(feeRecipient != address(0), "CreatePool: Non Zero Address");
require(msg.value >= createFee, "CreatePool: Value Amount");
// 转移代币到合约
IERC20(token).transferFrom(msg.sender, address(this), amount);
// 转移创建费用给接收地址
payable(feeRecipient).transfer(createFee);
// 创建代币曲线
bondingCurve[token] = Token ({
tokenMint: token,
virtualTokenReserves: initialVirtualTokenReserves,
virtualEthReserves: initialVirtualEthReserves,
realTokenReserves: amount,
realEthReserves: 0,
tokenTotalSupply: tokenTotalSupply,
mcapLimit: mcapLimit,
complete: false
});
emit CreatePool(token, msg.sender); // 触发创建池子事件
}
// 购买代币函数
function buy(
address token, // 代币地址
uint256 amount, // 购买数量
uint256 maxEthCost // 最大ETH成本
) payable public {
Token storage tokenCurve = bondingCurve[token];
require(amount > 0, "Should Larger than zero");
require(tokenCurve.complete == false, "Should Not Completed");
// 检查剩余代币百分比
uint256 featureAmount = tokenCurve.realTokenReserves - amount;
uint256 featurePercentage = featureAmount * 100 / tokenCurve.tokenTotalSupply;
require(featurePercentage > 20, "Buy Amount Over");
// 计算ETH成本
uint256 ethCost = calculateEthCost(tokenCurve, amount);
require(ethCost <= maxEthCost, "Max Eth Cost");
// 计算手续费
uint256 feeAmount = feeBasisPoint * ethCost / 10000;
uint256 ethAmount = ethCost - feeAmount;
require(msg.value >= ethCost, "Exceed ETH Cost");
// 转移手续费
payable(feeRecipient).transfer(feeAmount);
// 转移代币
IERC20(token).transfer(msg.sender, amount);
// 更新储备
tokenCurve.realTokenReserves -= amount;
tokenCurve.virtualTokenReserves -= amount;
tokenCurve.virtualEthReserves += ethAmount;
tokenCurve.realEthReserves += ethAmount;
// 检查是否达到完成条件
uint256 mcap = tokenCurve.virtualEthReserves * tokenCurve.tokenTotalSupply / tokenCurve.realTokenReserves;
uint256 percentage = tokenCurve.realTokenReserves * 100 / tokenCurve.tokenTotalSupply;
if (mcap > tokenCurve.mcapLimit || percentage < 20) {
tokenCurve.complete = true;
emit Complete(msg.sender, token, block.timestamp);
}
emit Trade(token, ethCost, amount, true, msg.sender, block.timestamp, tokenCurve.virtualEthReserves, tokenCurve.virtualTokenReserves);
}
// 出售代币函数
function sell(
address token, // 代币地址
uint256 amount, // 出售数量
uint256 minEthOutput // 最小ETH输出
) public {
Token storage tokenCurve = bondingCurve[token];
require(tokenCurve.complete == false, "Should Not Completed");
require(amount > 0, "Should Larger than zero");
// 计算ETH数量
uint256 ethCost = calculateEthCost(tokenCurve, amount);
if (tokenCurve.realEthReserves < ethCost) {
ethCost = tokenCurve.realEthReserves;
}
require(ethCost >= minEthOutput, "Should Be Larger than Min");
// 计算手续费
uint256 feeAmount = feeBasisPoint * ethCost / 10000;
// 转移ETH
payable(feeRecipient).transfer(feeAmount);
payable(msg.sender).transfer(ethCost - feeAmount);
// 转移代币
IERC20(token).transferFrom(msg.sender, address(this), amount);
// 更新储备
tokenCurve.realTokenReserves += amount;
tokenCurve.virtualTokenReserves += amount;
tokenCurve.virtualEthReserves -= ethCost;
tokenCurve.realEthReserves -= ethCost;
emit Trade(token, ethCost, amount, false, msg.sender, block.timestamp, tokenCurve.virtualEthReserves, tokenCurve.virtualTokenReserves);
}
// 提取资金函数
function withdraw(
address token // 代币地址
) public onlyOwner {
Token storage tokenCurve = bondingCurve[token];
require(tokenCurve.complete == true, "Should Be Completed");
// 转移ETH和代币给所有者
payable(owner).transfer(tokenCurve.realEthReserves);
IERC20(token).transfer(owner, tokenCurve.realTokenReserves);
}
// 计算ETH成本函数
function calculateEthCost(
Token memory token, // 代币信息
uint256 tokenAmount // 代币数量
) public pure returns (uint256) {
uint256 virtualTokenReserves = token.virtualTokenReserves;
uint256 pricePerToken = virtualTokenReserves - tokenAmount;
uint256 totalLiquidity = token.virtualEthReserves * token.virtualTokenReserves;
uint256 newEthReserves = totalLiquidity/pricePerToken;
uint256 ethCost = newEthReserves - token.virtualEthReserves;
return ethCost;
}
// 设置手续费接收地址
function setFeeRecipient(address newAddr) external onlyOwner {
require(newAddr != address(0), "Non zero Address");
feeRecipient = newAddr;
}
// 设置所有者地址
function setOwner(address newAddr) external onlyOwner {
require(newAddr != address(0), "Non zero Address");
owner = newAddr;
}
// 设置初始虚拟储备
function setInitialVirtualReserves(
uint256 initToken, // 初始代币储备
uint256 initEth // 初始ETH储备
) external onlyOwner {
require(initEth > 0 && initToken > 0, "Should Larger than zero");
initialVirtualTokenReserves = initToken;
initialVirtualEthReserves = initEth;
}
// 设置代币总供应量
function setTotalSupply(uint256 newSupply) external onlyOwner {
require(newSupply > 0, "Should Larger than zero");
tokenTotalSupply = newSupply;
}
// 设置市值上限
function setMcapLimit(uint256 newLimit) external onlyOwner {
require(newLimit > 0, "Should Larger than zero");
mcapLimit = newLimit;
}
}
2. TokenFactory.sol
// SPDX-License-Identifier: MIT // 指定开源协议为MIT
pragma solidity ^0.8.24; // 指定Solidity编译器版本
import "./Token.sol"; // 导入Token合约
// 定义PumpFun接口
interface IPumpFun {
// 创建池子函数
function createPool(
address token, // 代币地址
uint256 amount // 代币数量
) external payable;
// 获取创建费用函数
function getCreateFee() external view returns(uint256);
}
// TokenFactory合约
contract TokenFactory {
uint256 public currentTokenIndex = 0; // 当前代币索引
uint256 public immutable INITIAL_AMOUNT = 10**27; // 初始代币数量
address public contractAddress; // PumpFun合约地址
address public taxAddress = 0x044421aAbF1c584CD594F9C10B0BbC98546CF8bc; // 税收地址
// 代币结构体
struct TokenStructure {
address tokenAddress; // 代币合约地址
string tokenName; // 代币名称
string tokenSymbol; // 代币符号
uint256 totalSupply; // 总供应量
}
TokenStructure[] public tokens; // 代币数组
constructor () {} // 空构造函数
// 部署ERC20代币函数
function deployERC20Token (
string memory name, // 代币名称
string memory ticker // 代币符号
) public payable {
// 创建新代币
Token token = new Token(name, ticker, INITIAL_AMOUNT);
// 保存代币信息
tokens.push(
TokenStructure (
address(token),
name,
ticker,
INITIAL_AMOUNT
)
);
// 授权PumpFun合约
token.approve(contractAddress, INITIAL_AMOUNT);
uint256 balance = IPumpFun(contractAddress).getCreateFee();
// 创建交易池
require(msg.value >= balance, "Input Balance Should Be larger");
IPumpFun(contractAddress).createPool{value: balance}(address(token), INITIAL_AMOUNT);
}
// 设置PumpFun合约地址
function setPoolAddress (address newAddr) public {
require(newAddr != address(0), "Non zero Address");
contractAddress = newAddr;
}
}
3. Token.sol
// SPDX-License-Identifier: MIT // 指定开源协议为MIT
pragma solidity ^0.8.24; // 指定Solidity编译器版本
// 导入OpenZeppelin的ERC20合约
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// Token合约,继承自ERC20
contract Token is ERC20 {
// 构造函数
constructor(
string memory tokenName_, // 代币名称
string memory tokenSymbol_, // 代币符号
uint256 initialSupply // 初始供应量
) ERC20(tokenName_, tokenSymbol_) {
_mint(msg.sender, initialSupply); // 铸造初始代币给部署者
}
}
合约功能说明
这三个合约构成了完整的PumpFun智能合约系统:
-
PumpFun.sol
是核心交易合约,实现了基于虚拟储备的代币交易机制- 管理代币交易池
- 实现买卖功能
- 处理手续费
- 控制市场状态
-
TokenFactory.sol
是代币工厂合约,负责创建新的ERC20代币并自动初始化交易池- 创建新代币
- 记录代币信息
- 自动创建交易池
-
Token.sol
是标准的ERC20代币合约,用于创建新的代币- 实现ERC20标准
- 提供基础代币功能
每个合约都有其特定的功能和职责,通过接口和继承关系相互配合,形成一个完整的代币发行和交易系统。