Skip to content

Coinfair 限价单系统 - 双重撮合策略实现指南

🎯 概述

Coinfair 限价单系统采用创新的双重撮合策略:优先通过订单间直接撮合实现零滑点交易,剩余部分通过CLMM池子确保执行,为用户提供最优的交易体验。

✨ 核心特性

  • 双重撮合策略: 即时直接撮合 + 剩余部分CLMM撮合
  • 零滑点优先: 优先通过订单间直接匹配实现零滑点
  • 流动性保障: 剩余部分通过CLMM池子确保执行
  • CLMM 原生: 与集中流动性做市商完全集成

🔄 双重撮合策略

策略概述

我们的系统采用两步撮合法,最大化用户利益:

  1. 第一步:即时直接撮合

    • 新订单创建后立即尝试与对手订单匹配
    • 实现零滑点交易,保护用户利益
    • 使用Maker订单价格,保护流动性提供者
  2. 第二步:CLMM剩余撮合

    • 未撮合部分通过CLMM池子执行
    • 确保所有订单都能得到执行
    • 通过池子流动性发现最优价格

策略优势

撮合方式优势适用场景
即时直接撮合零滑点、即时执行、价格优先有对手订单匹配时
CLMM剩余撮合流动性保障、价格发现、风险分散无对手订单或部分撮合后

🏗️ 系统架构

双重撮合流程图

结果处理

第二步:CLMM剩余撮合

第一步:即时直接撮合

用户层

创建订单

验证并锁定代币

存储到订单簿

立即尝试撮合

找到匹配订单?

执行直接撮合

进入第二步

计算剩余数量

有剩余数量?

通过CLMM池子执行

订单完成

更新订单状态

转移代币

发布事件

核心架构组件

  1. 订单管理层: 订单创建、取消和生命周期管理
  2. 即时撮合引擎: 零滑点订单间直接撮合
  3. CLMM剩余撮合引擎: 处理未撮合部分
  4. 智能路由系统: 自动选择最优撮合路径

🔧 核心组件

1. 数据结构

LimitOrder

struct LimitOrder has key, store {
    id: u64,                           // 唯一订单ID
    owner: address,                    // 订单所有者
    token_in: Object<Metadata>,        // 输入代币元数据
    token_out: Object<Metadata>,       // 输出代币元数据
    amount_in: u64,                    // 输入金额
    tick: i64,                         // 目标价格tick
    filled: u64,                       // 已成交金额
    remaining: u64,                    // 剩余未成交金额
    status: u8,                        // 订单状态
    order_type: u8,                    // 订单类型 (买单/卖单)
    created_at: u64,                   // 创建时间戳
    updated_at: u64,                   // 最后更新时间戳
}

OrderBook

struct OrderBook has key {
    // 使用 SkipList 的价格索引
    buy_orders: SkipList<i64, vector<u64>>,    // 买单 (tick 高→低)
    sell_orders: SkipList<i64, vector<u64>>,   // 卖单 (tick 低→高)
    
    // 使用 SmartTable 的订单存储
    orders: SmartTable<u64, LimitOrder>,          // 订单详情 (ID → 订单)
    order_nodes: SmartTable<u64, SkipListNode>,   // SkipList 节点 (ID → 节点)
    user_orders: SmartTable<address, vector<u64>>, // 用户订单索引
    
    // 系统状态
    next_order_id: u64,                           // 下一个订单ID
    total_orders: u64,                            // 总订单数量
    total_volume: u128,                           // 总交易量
}

2. 订单状态与类型

// 订单状态常量
const ORDER_STATUS_ACTIVE: u8 = 0;           // 活跃
const ORDER_STATUS_PARTIALLY_FILLED: u8 = 1; // 部分成交(等待CLMM撮合)
const ORDER_STATUS_FILLED: u8 = 2;           // 完全成交
const ORDER_STATUS_CANCELLED: u8 = 3;        // 已取消
const ORDER_STATUS_EXPIRED: u8 = 4;          // 已过期
const ORDER_STATUS_REJECTED: u8 = 5;         // 已拒绝


// 订单类型常量
const ORDER_TYPE_BUY: u8 = 0;   // 买单
const ORDER_TYPE_SELL: u8 = 1;  // 卖单

🚀 实现详情

1. 订单创建与双重撮合

创建订单(自动触发双重撮合)

public fun create_limit_order(
    account: &signer,
    token_in: Object<Metadata>,
    token_out: Object<Metadata>,
    amount_in: u64,
    tick: i64,
    order_type: u8,
    expiration_time: u64
): u64

执行流程:

  1. 参数验证和边界检查
  2. 代币转移和锁定
  3. 创建订单并存储
  4. 自动触发双重撮合策略

双重撮合执行逻辑

/// 新订单创建后的双重撮合流程
fun execute_dual_matching_strategy(
    order_book: &mut OrderBook, 
    new_order_id: u64
): (u64, u64) // 返回:(直接撮合数量, CLMM撮合数量)


/// 第一步:即时直接撮合
fun execute_immediate_matching(
    order_book: &mut OrderBook,
    order_id: u64
): u64 // 返回直接撮合的数量


/// 第二步:CLMM剩余撮合
fun execute_clmm_remaining_matching(
    order_book: &mut OrderBook,
    order_id: u64,
    remaining_amount: u64,
    pool_address: address
): (u64, u64) // 返回:(实际输入, 实际输出)

2. 即时直接撮合引擎

核心撮合函数

/// 查找可匹配的对手订单
fun find_matching_orders(
    order_book: &OrderBook, 
    order_tick: i64, 
    order_type: u8,
    pool: address
): vector<u64>


/// 执行两个订单的撮合
fun execute_order_match(
    order_book: &mut OrderBook, 
    order_id1: u64, 
    order_id2: u64
): u64 // 返回撮合数量


/// 批量撮合处理
public fun execute_batch_matching(order_book_address: address): u64

撮合条件:

  • 买单撮合: 寻找 sell_tick <= buy_tick 的卖单
  • 卖单撮合: 寻找 buy_tick >= sell_tick 的买单
  • 价格优先: 使用Maker订单价格执行
  • 时间优先: 相同价格下先来先服务(FIFO)

3. CLMM剩余撮合引擎

AfterSwap Hook 集成

public fun after_swap_hook(
    pool_address: address,
    current_tick: i64
): vector<u64>

执行流程:

  1. 获取当前池子 tick
  2. 查找需要CLMM撮合的订单(基于 tick 范围)
  3. 按优先级排序(tick + 时间 + 数量)
  4. 执行剩余部分CLMM撮合
  5. 更新订单状态
  6. 发布执行事件

订单执行引擎

fun execute_limit_order_via_clmm(
    order: &mut LimitOrder,
    pool_address: address,
    current_tick: i64
): (u64, u64)

执行逻辑:

  • tick 条件验证(买单:current_tick > order.tick,卖单:current_tick < order.tick)
  • 数量计算和调整(仅处理剩余未撮合部分)
  • 滑点保护检查
  • CLMM池子交换调用
  • 结果验证和更新

📡 事件系统

双重撮合事件链

#[event]
struct OrderCreatedEvent has drop, store {
    order_id: u64,
    owner: address,
    token_in: Object<Metadata>,
    token_out: Object<Metadata>,
    amount_in: u64,
    tick: i64,
    order_type: u8,
    expiration_time: u64,
    timestamp: u64,
}


#[event]
struct OrderMatchedEvent has drop, store {
    buy_order_id: u64,       // 买单ID
    sell_order_id: u64,      // 卖单ID
    buy_owner: address,      // 买方地址
    sell_owner: address,     // 卖方地址
    matched_amount: u64,     // 撮合数量
    execution_tick: i64,     // 执行价格tick
    match_type: u8,          // 撮合类型:0=直接撮合,1=CLMM撮合
    timestamp: u64,          // 撮合时间戳
}


#[event]
struct OrderExecutedEvent has drop, store {
    order_id: u64,
    owner: address,
    amount_filled: u64,      // 本次成交数量
    amount_out: u64,         // 本次输出数量
    remaining: u64,          // 剩余数量
    execution_tick: i64,     // 执行价格tick
    execution_type: u8,      // 执行类型:0=直接撮合,1=CLMM撮合
    timestamp: u64,          // 执行时间戳
}


#[event]
struct OrderCompletedEvent has drop, store {
    order_id: u64,
    owner: address,
    total_filled: u64,       // 总成交数量
    total_out: u64,          // 总输出数量
    direct_match_amount: u64, // 直接撮合数量
    clmm_match_amount: u64,   // CLMM撮合数量
    completion_time: u64,     // 完成时间戳
}

⚡ 性能与优化

1. 双重撮合策略性能优势

即时直接撮合优势:

  • 零滑点执行: 订单间直接匹配,无需通过AMM池子
  • 即时响应: 新订单创建时立即尝试撮合
  • 价格优先: 使用Maker订单价格,保护流动性提供者
  • 高效处理: 双指针算法实现O(n)批量撮合

CLMM剩余撮合优势:

  • 流动性保障: 确保所有订单都能得到执行
  • 价格发现: 通过池子流动性发现最优价格
  • 风险分散: 分散大单对市场的影响
  • CLMM 原生: 直接 tick 索引,与池子 tick 系统完全兼容

🧪 测试与质量

双重撮合策略测试

#[test]
fun test_dual_matching_strategy() { /* 双重撮合策略测试 */ }
#[test]
fun test_immediate_matching_only() { /* 仅即时撮合测试 */ }
#[test]
fun test_clmm_remaining_only() { /* 仅CLMM剩余撮合测试 */ }
#[test]
fun test_mixed_execution_scenario() { /* 混合执行场景测试 */ }
#[test]
fun test_order_creation_flow() { /* 订单创建流程测试 */ }
#[test]
fun test_cancel_order() { /* 订单取消测试 */ }
#[test]
fun test_get_order_details() { /* 订单查询测试 */ }
#[test]
fun test_cancel_order_unauthorized() { /* 权限验证测试 */ }
#[test]
fun test_create_order_invalid_params() { /* 参数验证测试 */ }
#[test]
fun test_multiple_orders_same_price() { /* 价格聚合测试 */ }
#[test]
fun test_cancel_all_user_orders() { /* 批量操作测试 */ }
#[test]
fun test_order_expiration() { /* 过期处理测试 */ }
#[test]
fun test_large_order_book_performance() { /* 性能测试 */ }
#[test]
fun test_concurrent_order_creation() { /* 并发测试 */ }

📋 使用示例

1. 基础订单操作(自动双重撮合)

创建买单

// 创建 USDC → APT 买单
let order_id = create_limit_order(
    &user,
    token_usdc,
    token_apt,
    1000000,      // 1 USDC
    276325,       // 目标 tick (~1.25 USDC/APT)
    ORDER_TYPE_BUY,
    1735689600    // 过期时间
);


// 系统自动执行双重撮合策略:
// 1. 即时撮合:寻找匹配的卖单进行零滑点撮合
// 2. CLMM剩余撮合:未撮合部分通过CLMM池子执行

创建卖单

// 创建 APT → USDC 卖单
let order_id = create_limit_order(
    &user,
    token_apt,
    token_usdc,
    100000000,    // 1 APT
    276325,       // 目标 tick (~1.25 USDC/APT)
    ORDER_TYPE_SELL,
    1735689600    // 过期时间
);


// 系统自动执行双重撮合策略:
// 1. 即时撮合:寻找匹配的买单进行零滑点撮合
// 2. CLMM剩余撮合:未撮合部分通过CLMM池子执行

2. 手动控制撮合策略

仅执行即时撮合

// 手动触发即时撮合
let matched_amount = execute_immediate_matching(
    &mut order_book,
    order_id
);
// 返回: 直接撮合的数量

仅执行CLMM剩余撮合

// 手动触发CLMM剩余撮合
let (amount_in, amount_out) = execute_clmm_remaining_matching(
    &mut order_book,
    order_id,
    remaining_amount,
    pool_address
);
// 返回: (实际输入金额, 实际输出金额)

完整双重撮合流程

// 手动执行完整双重撮合策略
let (direct_amount, clmm_amount) = execute_dual_matching_strategy(
    &mut order_book,
    order_id
);
// 返回: (直接撮合数量, CLMM撮合数量)

3. 订单管理

// 取消特定订单
cancel_order(&user, order_id);


// 取消用户所有订单
let cancelled_count = cancel_all_user_orders(&user);


// 获取订单详情
let order_opt = get_order_details(order_id);
if (order_opt.is_some()) {
    let order = order_opt.destroy_some();
    // 处理订单信息
};


// 按 tick 查询订单
let orders_at_tick = get_orders_by_tick(276325, ORDER_TYPE_BUY);


// 按 tick 范围查询订单
let orders_in_range = get_orders_by_price_range(276000, 277000, ORDER_TYPE_BUY);

4. 高级操作

批量撮合

// 执行全局批量撮合
let matched_pairs = execute_batch_matching(order_book_address);
// 返回: 成功撮合的订单对数量


// 获取订单簿统计信息
let stats = get_order_book_stats(order_book_address);
// 返回: (总订单数, 活跃订单数, 总成交量)

事件监控

// 监控双重撮合事件
event::emit(OrderMatchedEvent {
    buy_order_id: 123,
    sell_order_id: 456, 
    buy_owner: @user_a,
    sell_owner: @user_b,
    matched_amount: 100000000, // 1 APT
    execution_tick: 405000,    // 执行价格tick
    match_type: 0,             // 0=直接撮合,1=CLMM撮合
    timestamp: 1735689600,
});

此实现采用创新的双重撮合策略,为 Coinfair DEX 提供专业级的限价单交易体验,最大化用户利益并确保流动性。