# AI+Web3实战营日志 #3 | Router合约

By [Keegan小钢](https://paragraph.com/@keeganlee) · 2025-09-21

---

这是我的 [AI + Web3 实战营](https://mp.weixin.qq.com/s/tTAaUCIfRaHS8bLJese27Q)的第三篇研发日志，前两篇如下：

[**AI+Web3实战营日志 #1｜开营**](https://mp.weixin.qq.com/s?__biz=MzA5OTI1NDE0Mw==&mid=2652495285&idx=1&sn=49acd14afddf10e8bd0e0813f07f90a0&scene=21#wechat_redirect)

[**AI+Web3实战营日志 #2 | 完成底层合约**](https://mp.weixin.qq.com/s?__biz=MzA5OTI1NDE0Mw==&mid=2652495299&idx=1&sn=bf08bcdf92558408615ca17c097f46ba&scene=21#wechat_redirect)

* * *

另外，关于 AI + Web3 实战营的相关介绍则有如下几篇文章：

[**我要启动 AI + Web3 实战营了**](https://mp.weixin.qq.com/s?__biz=MzA5OTI1NDE0Mw==&mid=2652495268&idx=1&sn=c226a51bc06d180858a41fa9becbf752&scene=21#wechat_redirect)

[**再谈 AI+Web3 实战营：这到底能带给你什么？**](https://mp.weixin.qq.com/s?__biz=MzA5OTI1NDE0Mw==&mid=2652495273&idx=1&sn=628a703d76cc808a0484f576234f2c7a&scene=21#wechat_redirect)

[**AI+Web3实战营，9月15日正式开营**](https://mp.weixin.qq.com/s?__biz=MzA5OTI1NDE0Mw==&mid=2652495279&idx=1&sn=4369256be0f5ad49989242a35eab3a04&scene=21#wechat_redirect)

* * *

背景
--

上篇日志里我们完成了 **BlockETFCore 底层合约**，它能处理多资产按比例的申购赎回。问题是，这样的操作对普通用户来说太复杂了：要一次性准备好多种资产，并且还要按比例。

所以我们需要在 Core 合约之上，再搭建一个更友好的入口 —— **Router 合约**。它的目标很简单：让用户只用 **单一资产（比如 USDT）** 就能直接申购和赎回 ETF。

* * *

为什么选择 Router 模式？
----------------

一开始我们评估了几种方案：

*   **直接改 Core**：会破坏架构的纯净性
    
*   **Wrapper 包装**：逻辑变复杂，不利于长期维护
    
*   **Router 独立层**：职责清晰，逻辑独立，可单独升级
    

最终，我们选择了 **Router 模式**，它能保证 Core 保持干净，Router 负责对接用户体验，两者分工明确。

* * *

MVP 功能
------

第一版我们只聚焦几个关键点：

*   **单一入口**：只支持 USDT
    
*   **目标资产**：BTCB、ETH、XRP、SOL、WBNB
    
*   **核心函数**：`mintWithUSDT()` 和 `burnToUSDT()`
    
*   **滑点保护**：避免用户损失
    
*   **DEX 集成**：先用 PancakeSwap 做流动性入口
    

* * *

研发过程中的几个挑战
----------

### 1\. PancakeSwap 版本选择

一开始我以为直接上 V3 就行，但发现不同资产的流动性分布差异很大：

*   BTCB/ETH/XRP/SOL：V3 更好
    
*   WBNB：只在 V2 有流动性
    

所以最后采用了 **V2+V3 混合架构**。

### 2\. 路由策略

最初的设计是所有兑换都走 USDT→WBNB→目标资产。但会发现，这样多走了一跳，增加了滑点和 Gas 成本。更重要的是，USDT/WBNB 在 V3 中并没有流动性。

于是改成了：

*   有配置的池就走配置池
    
*   没有配置则走默认直换
    

这个调整大大减少了额外损耗。

### 3\. 费率配置

从一开始的“所有对统一 0.25%”，到尝试“动态费率算法”，最后回归到最简单的方式：**直接配置池地址**。实践证明，简单才是最可靠的。

### 4\. 混合 DEX 集成

根据资产特性决定走 V2 还是 V3，比如：

*   WBNB：走 V2
    
*   其他：走 V3
    

Router 内部做了自动判断，用户无感知。

* * *

实现要点
----

Router 主要暴露了两个函数：

    function mintWithUSDT(...) external returns (uint256 shares);
    function burnToUSDT(...) external returns (uint256 usdtAmount);
    

流程很直观：

*   **申购**：用户给 USDT → Router 拆分兑换成目标资产 → 调用 Core 铸造份额 → 返回多余 USDT
    
*   **赎回**：用户交回份额 → Core 退回底层资产 → Router 换回 USDT → 转给用户
    

这中间的优化点在于：

*   用 `mintExactShares` 来提高精度
    
*   支持管理员灵活配置池和滑点参数
    
*   保留紧急暂停功能
    

* * *

成果展示
----

最终架构大致是这样的：

    USDT <——> Router <——> Core
                 │
                 ├─ PancakeSwap V2 (WBNB)
                 └─ PancakeSwap V3 (BTCB/ETH/XRP/SOL)
    

它的特性包括：

*   智能路由，自动走最优路径
    
*   V2+V3 混合，充分利用流动性
    
*   精确份额控制，减少滑点
    
*   灵活配置，可快速调整
    

* * *

我的收获
----

1.  **实地调研很重要**：不要依赖假设，链上真实流动性才是决策依据
    
2.  **从复杂到简单**：很多时候演进过程很曲折，但最终最简洁的方案往往最好
    
3.  **架构分离的价值**：Core 专注 ETF，Router 专注交互，这样清晰又可维护
    
4.  **用户体验优先**：功能选择始终围绕“用户用起来是否方便”
    

* * *

下一步
---

完成 ETFRouterV1 之后，下一步我们就要实现 RebalanceManager 了，这也是最复杂的一个模块。

* * *

📌 小结一下：Router 合约让用户终于可以用一枚 USDT 就轻松申购/赎回 ETF 了。对用户来说体验更直观，对架构来说依旧保持了清晰分离。这是我们实战营迭代中迈出的关键一步。

---

*Originally published on [Keegan小钢](https://paragraph.com/@keeganlee/ai-web3-3-router)*
