代币交易所系统
代币交易所是一个用于管理代币交易和流动性的系统。本教程将介绍如何实现一个安全可靠的交易所系统。
功能特性
- 交易管理
- 流动性管理
- 价格发现
- 手续费管理
- 紧急处理
合约实现
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
/**
* @title TokenExchange
* @dev 代币交易所合约实现
*/
contract TokenExchange is Ownable, ReentrancyGuard, Pausable {
using SafeMath for uint256;
// 交易对信息
struct PairInfo {
address token0; // 代币0
address token1; // 代币1
uint256 reserve0; // 储备0
uint256 reserve1; // 储备1
uint256 totalSupply; // 总供应量
uint256 fee; // 手续费率
bool isActive; // 是否激活
}
// 订单信息
struct Order {
address maker; // 挂单者
address token0; // 卖出代币
address token1; // 买入代币
uint256 amount0; // 卖出数量
uint256 amount1; // 买入数量
uint256 timestamp; // 时间戳
bool isActive; // 是否激活
}
// 配置信息
struct ExchangeConfig {
uint256 minAmount; // 最小数量
uint256 maxAmount; // 最大数量
uint256 baseFee; // 基础手续费
uint256 maxFee; // 最大手续费
bool requiresApproval; // 是否需要审批
bool isActive; // 是否激活
}
// 状态变量
mapping(bytes32 => PairInfo) public pairs; // 交易对
mapping(bytes32 => Order) public orders; // 订单
mapping(address => mapping(address => uint256)) public liquidity; // 流动性
mapping(address => bool) public operators; // 操作员
ExchangeConfig public config; // 配置信息
// 事件
event PairCreated(bytes32 indexed pairId, address indexed token0, address indexed token1);
event LiquidityAdded(bytes32 indexed pairId, address indexed provider, uint256 amount0, uint256 amount1);
event LiquidityRemoved(bytes32 indexed pairId, address indexed provider, uint256 amount0, uint256 amount1);
event OrderCreated(bytes32 indexed orderId, address indexed maker, uint256 amount0, uint256 amount1);
event OrderExecuted(bytes32 indexed orderId, address indexed taker, uint256 amount0, uint256 amount1);
event OrderCancelled(bytes32 indexed orderId);
event OperatorUpdated(address indexed operator, bool status);
event ConfigUpdated(uint256 minAmount, uint256 maxAmount, uint256 baseFee);
/**
* @dev 构造函数
*/
constructor(
uint256 _minAmount,
uint256 _maxAmount,
uint256 _baseFee,
uint256 _maxFee
) {
config = ExchangeConfig({
minAmount: _minAmount,
maxAmount: _maxAmount,
baseFee: _baseFee,
maxFee: _maxFee,
requiresApproval: true,
isActive: true
});
}
/**
* @dev 创建交易对
*/
function createPair(
address _token0,
address _token1,
uint256 _fee
) external onlyOperator whenNotPaused returns (bytes32) {
require(_token0 != address(0) && _token1 != address(0), "Invalid tokens");
require(_token0 != _token1, "Same tokens");
require(_fee <= config.maxFee, "Fee too high");
bytes32 pairId = keccak256(abi.encodePacked(_token0, _token1));
require(!pairs[pairId].isActive, "Pair exists");
pairs[pairId] = PairInfo({
token0: _token0,
token1: _token1,
reserve0: 0,
reserve1: 0,
totalSupply: 0,
fee: _fee,
isActive: true
});
emit PairCreated(pairId, _token0, _token1);
return pairId;
}
/**
* @dev 添加流动性
*/
function addLiquidity(
bytes32 _pairId,
uint256 _amount0,
uint256 _amount1
) external nonReentrant whenNotPaused returns (uint256) {
PairInfo storage pair = pairs[_pairId];
require(pair.isActive, "Pair not active");
require(_amount0 >= config.minAmount && _amount1 >= config.minAmount, "Amount too low");
require(_amount0 <= config.maxAmount && _amount1 <= config.maxAmount, "Amount too high");
uint256 liquidity0 = _amount0;
uint256 liquidity1 = _amount1;
if (pair.totalSupply > 0) {
require(
_amount0.mul(pair.reserve1) == _amount1.mul(pair.reserve0),
"Invalid ratio"
);
}
require(
IERC20(pair.token0).transferFrom(msg.sender, address(this), _amount0),
"Transfer failed"
);
require(
IERC20(pair.token1).transferFrom(msg.sender, address(this), _amount1),
"Transfer failed"
);
pair.reserve0 = pair.reserve0.add(_amount0);
pair.reserve1 = pair.reserve1.add(_amount1);
pair.totalSupply = pair.totalSupply.add(liquidity0);
liquidity[_pairId][msg.sender] = liquidity[_pairId][msg.sender].add(liquidity0);
emit LiquidityAdded(_pairId, msg.sender, _amount0, _amount1);
return liquidity0;
}
/**
* @dev 移除流动性
*/
function removeLiquidity(
bytes32 _pairId,
uint256 _liquidity
) external nonReentrant whenNotPaused returns (uint256, uint256) {
PairInfo storage pair = pairs[_pairId];
require(pair.isActive, "Pair not active");
require(_liquidity > 0, "Invalid liquidity");
require(liquidity[_pairId][msg.sender] >= _liquidity, "Insufficient liquidity");
uint256 amount0 = _liquidity.mul(pair.reserve0).div(pair.totalSupply);
uint256 amount1 = _liquidity.mul(pair.reserve1).div(pair.totalSupply);
liquidity[_pairId][msg.sender] = liquidity[_pairId][msg.sender].sub(_liquidity);
pair.totalSupply = pair.totalSupply.sub(_liquidity);
pair.reserve0 = pair.reserve0.sub(amount0);
pair.reserve1 = pair.reserve1.sub(amount1);
require(
IERC20(pair.token0).transfer(msg.sender, amount0),
"Transfer failed"
);
require(
IERC20(pair.token1).transfer(msg.sender, amount1),
"Transfer failed"
);
emit LiquidityRemoved(_pairId, msg.sender, amount0, amount1);
return (amount0, amount1);
}
/**
* @dev 创建订单
*/
function createOrder(
address _token0,
address _token1,
uint256 _amount0,
uint256 _amount1
) external nonReentrant whenNotPaused returns (bytes32) {
require(_amount0 >= config.minAmount && _amount1 >= config.minAmount, "Amount too low");
require(_amount0 <= config.maxAmount && _amount1 <= config.maxAmount, "Amount too high");
bytes32 orderId = keccak256(abi.encodePacked(
block.timestamp,
msg.sender,
_token0,
_token1,
_amount0,
_amount1
));
orders[orderId] = Order({
maker: msg.sender,
token0: _token0,
token1: _token1,
amount0: _amount0,
amount1: _amount1,
timestamp: block.timestamp,
isActive: true
});
require(
IERC20(_token0).transferFrom(msg.sender, address(this), _amount0),
"Transfer failed"
);
emit OrderCreated(orderId, msg.sender, _amount0, _amount1);
return orderId;
}
/**
* @dev 执行订单
*/
function executeOrder(
bytes32 _orderId
) external nonReentrant whenNotPaused {
Order storage order = orders[_orderId];
require(order.isActive, "Order not active");
require(msg.sender != order.maker, "Cannot execute own order");
require(
IERC20(order.token1).transferFrom(msg.sender, order.maker, order.amount1),
"Transfer failed"
);
require(
IERC20(order.token0).transfer(msg.sender, order.amount0),
"Transfer failed"
);
order.isActive = false;
emit OrderExecuted(_orderId, msg.sender, order.amount0, order.amount1);
}
/**
* @dev 取消订单
*/
function cancelOrder(bytes32 _orderId) external nonReentrant whenNotPaused {
Order storage order = orders[_orderId];
require(order.isActive, "Order not active");
require(msg.sender == order.maker, "Not order maker");
order.isActive = false;
require(
IERC20(order.token0).transfer(order.maker, order.amount0),
"Transfer failed"
);
emit OrderCancelled(_orderId);
}
/**
* @dev 获取交易对信息
*/
function getPairInfo(bytes32 _pairId)
external
view
returns (
address token0,
address token1,
uint256 reserve0,
uint256 reserve1,
uint256 totalSupply,
uint256 fee,
bool isActive
)
{
PairInfo storage pair = pairs[_pairId];
return (
pair.token0,
pair.token1,
pair.reserve0,
pair.reserve1,
pair.totalSupply,
pair.fee,
pair.isActive
);
}
/**
* @dev 获取订单信息
*/
function getOrderInfo(bytes32 _orderId)
external
view
returns (
address maker,
address token0,
address token1,
uint256 amount0,
uint256 amount1,
uint256 timestamp,
bool isActive
)
{
Order storage order = orders[_orderId];
return (
order.maker,
order.token0,
order.token1,
order.amount0,
order.amount1,
order.timestamp,
order.isActive
);
}
/**
* @dev 计算交易金额
*/
function getAmountOut(
bytes32 _pairId,
uint256 _amountIn,
bool _isToken0
) external view returns (uint256) {
PairInfo storage pair = pairs[_pairId];
require(pair.isActive, "Pair not active");
require(_amountIn > 0, "Invalid amount");
uint256 reserveIn = _isToken0 ? pair.reserve0 : pair.reserve1;
uint256 reserveOut = _isToken0 ? pair.reserve1 : pair.reserve0;
uint256 amountInWithFee = _amountIn.mul(1000 - pair.fee);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
return numerator.div(denominator);
}
/**
* @dev 设置操作员
*/
function setOperator(address _operator, bool _status) external onlyOwner {
operators[_operator] = _status;
emit OperatorUpdated(_operator, _status);
}
/**
* @dev 更新配置
*/
function updateConfig(
uint256 _minAmount,
uint256 _maxAmount,
uint256 _baseFee,
uint256 _maxFee,
bool _requiresApproval
) external onlyOwner {
require(_maxAmount > _minAmount, "Invalid amounts");
require(_maxFee >= _baseFee, "Invalid fees");
config.minAmount = _minAmount;
config.maxAmount = _maxAmount;
config.baseFee = _baseFee;
config.maxFee = _maxFee;
config.requiresApproval = _requiresApproval;
emit ConfigUpdated(_minAmount, _maxAmount, _baseFee);
}
/**
* @dev 暂停/恢复合约
*/
function setPaused(bool _paused) external onlyOwner {
if (_paused) {
_pause();
} else {
_unpause();
}
}
/**
* @dev 紧急提取
*/
function emergencyWithdraw(
address _token,
address _to,
uint256 _amount
) external onlyOwner {
require(_to != address(0), "Invalid address");
IERC20(_token).transfer(_to, _amount);
}
/**
* @dev 检查是否是操作员
*/
modifier onlyOperator() {
require(operators[msg.sender] || msg.sender == owner(), "Not operator");
_;
}
}
关键概念
交易管理
交易功能包括:
- 订单创建
- 订单执行
- 订单取消
- 价格发现
流动性管理
流动性功能包括:
- 添加流动性
- 移除流动性
- 流动性计算
- 储备管理
手续费管理
手续费功能包括:
- 费率设置
- 费用计算
- 费用分配
- 收益分配
安全考虑
交易安全
- 订单验证
- 价格验证
- 数量验证
- 状态检查
流动性安全
- 储备验证
- 比例检查
- 余额验证
- 状态保护
系统安全
- 权限控制
- 暂停机制
- 重入防护
- 状态同步
升级安全
- 配置更新
- 费率调整
- 状态迁移
- 紧急处理
最佳实践
交易管理
- 订单验证
- 价格管理
- 状态追踪
- 异常处理
流动性管理
- 储备管理
- 比例控制
- 余额验证
- 状态管理
风险管理
- 价格监控
- 异常检测
- 风险预警
- 应急处理
系统维护
- 参数优化
- 性能监控
- 安全审计
- 升级预案
扩展功能
- 多币种支持
- 限价订单
- 市价订单
- 自动做市
- 价格预言机
应用场景
代币交易
- 限价交易
- 市价交易
- 流动性提供
- 做市交易
资产管理
- 流动性管理
- 资产配置
- 风险控制
- 收益优化
市场管理
- 价格发现
- 流动性维护
- 市场稳定
- 风险控制
总结
代币交易所系统是DeFi生态的重要基础设施。通过本教程,你可以:
- 实现交易功能
- 管理流动性
- 优化交易机制
- 提供安全保护
常见问题解答(FAQ)
基础概念
Q: 什么是代币交易所?
A: 代币交易所是一种去中心化交易机制,主要特点包括:
- 自动化代币交换
- 流动性池管理
- 价格自动发现
- 无需对手方
- 透明公平交易
Q: 交易所有哪些类型?
A: 主要类型包括:
- 自动做市商(AMM)
- 订单簿模式
- 混合交易模式
- 稳定币交易对
- 跨链交易所
操作相关
Q: 如何使用代币交易所?
A: 使用步骤包括:
- 连接钱包
- 选择交易对
- 设置交易参数
- 确认交易
- 等待完成
Q: 如何提供流动性?
A: 操作步骤包括:
- 准备代币对
- 选择流动性池
- 设置注入比例
- 确认添加
- 获取LP代币
安全相关
Q: 交易所有哪些风险?
A: 主要风险包括:
- 无常损失风险
- 价格滑点
- 智能合约漏洞
- 流动性不足
- 市场操纵
Q: 如何确保交易安全?
A: 安全措施包括:
- 设置滑点保护
- 限制交易规模
- 多重签名控制
- 价格预言机
- 紧急暂停机制