找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

972

积分

0

好友

138

主题
发表于 前天 11:39 | 查看: 4| 回复: 0

在近期进行的fork主网集成测试中,发现BlockLever路由合约中引入的QuoterV3合约无法正常工作。通过集中调试,最终定位并修复了问题,确保集成测试顺利通过。

背景介绍

许多熟悉UniswapV3的技术人员都知道,其QuoterV2合约提供了几个核心报价函数:

  • quoteExactInputSingle
  • quoteExactOutputSingle
  • quoteExactInput
  • quoteExactOutput

然而,由于底层实现会直接调用pool合约的swap函数,这些quote函数无法声明为view函数,这给许多合约集成项目带来了不便。

BlockLever项目并未接入UniswapV3,而是选择了PancakeSwapV3。PancakeSwapV3基于UniswapV3进行了微小调整,其Quoter合约与UniswapV3类似,报价函数同样不是只读的view函数。

BlockLever的路由合约定义了以下几个预览函数:

  • previewBorrowToBuy
  • previewSellToRepay
  • previewBorrowToSell
  • previewBuyToRepay

这些预览函数需要调用Quoter合约获取报价。如果直接使用上述quote函数,那么preview函数也无法声明为view函数。

在DeFi协议中,preview类函数不仅用于开发调试,还承担着关键角色:

  1. 前端报价预览
  2. 区块浏览器直接查询
  3. 第三方合约只读调用
  4. 风控与策略模拟

如果这些函数非view,将导致:

  • 前端需通过交易调用,体验差
  • 区块浏览器无法直接查询
  • 第三方协议集成困难
  • 用户策略预估成本高

因此,BlockLever明确将所有preview函数定义为纯只读函数,这是产品级设计决策,而非技术细节。

解决方案是使用QuoterV3替代QuoterV2,下面介绍相关库。

view-quoter-v3

Uniswap后来实现了v3版本的Quoter合约,但作为一个独立仓库存在,未像QuoterV2那样广泛认知。

项目GitHub地址:https://github.com/Uniswap/view-quoter-v3

该仓库中的Quoter合约提供了与QuoterV2一致的4个核心报价函数,并新增了两个支持直接指定Pool的函数:

  • quoteExactInputSingleWithPool
  • quoteExactOutputSingleWithPool

关键改进:所有报价函数均声明为view函数,这正是BlockLever所需的能力。

其核心思路是将原本依赖swap执行的计算逻辑重写为纯计算逻辑,避免状态修改,实现安全只读调用。

Uniswap官方已在BNB Chain部署该合约。但由于BlockLever接入的是PancakeSwapV3,无法直接复用。PancakeSwap官方未提供对应的view Quoter合约,因此我们选择fork该项目并适配PancakeSwapV3,以满足路由合约预览函数调用需求。

实际上,在首期实战营项目BlockETF中,我们已实现过一版适配PancakeSwap的只读Quoter合约。但BlockETF的预览逻辑结合了价格预言机数据,即使Quoter存在问题,运行时也不会明显异常。这导致我们可能误以为BlockETF中的Quoter实现完全可用。

此次问题在BlockLever的主网fork集成测试中暴露,再次验证:只有在真实环境下进行系统级集成测试,才能发现被业务逻辑掩盖的底层隐患。

适配PancakeSwap的核心改动

view-quoter-v3适配为支持PancakeSwapV3,改动主要集中在Pool地址计算逻辑Pool接口定义差异两方面。

1. PoolAddress库的适配

首先需修改PoolAddress库合约,有两个关键调整点。

第一处修改POOL_INIT_CODE_HASH常量,需从UniswapV3Pool的值替换为PancakeSwapV3Pool对应的值,否则Pool地址计算会出错。

第二处修改位于computeAddress函数。UniswapV3使用Factory合约地址计算Pool地址,而PancakeSwapV3使用Deployer合约地址。因此,函数中的factory参数需整体替换为PancakeSwapV3的deployer地址。

这两处差异均可通过对比PancakeSwap官方仓库中的PoolAddress实现确认。

2. Pool接口类型的替换

第二类改动涉及多个引用IUniswapV3Pool接口的合约。在这些地方,我们统一将接口替换为IPancakeV3Pool。此问题正是在本次BlockLever主网fork集成测试中暴露的。

根本原因在于两者接口细节不完全一致。典型差异是slot0()函数的返回值类型:

  • 在IUniswapV3Pool中,feeProtocol字段类型为uint8
  • 在IPancakeV3Pool中,对应字段类型为uint32

这种类型差异在单元测试或模拟环境中可能不触发问题,但在fork主网读取真实Pool状态时,会导致ABI解码错误或逻辑异常

3. 为什么问题易被忽略

UniswapV3与PancakeSwapV3的Pool接口高度相似,容易让人下意识直接复用定义。如果没有真实链上环境的完整集成测试,这类类型级别的不一致可能长期潜伏。

小结

此次适配过程再次印证:在DeFi协议集成中,“接口看起来一样”不等于“可以安全复用”。 即使协议分支同源,也必须以真实部署实现为准,逐项验证接口、参数和数据类型。

集成测试的真正价值

回顾来看,Quoter问题不是“代码错误”,而是系统级集成测试才能暴露的问题。单元测试中逻辑看似正确,但与真实链上协议交互时,细微差异会被放大。

在BlockLever研发中,fork主网后的集成测试是必经阶段,而非可选。对实战营学员而言,此阶段同样关键:真正的DeFi工程能力在于让系统在真实环境中稳定、可预期、可验证地运行




上一篇:无线通信衰落类型解析:从慢衰落到快衰落及移动通信抗衰落策略
下一篇:F-Score模型:A股基本面选股实战与Python量化策略分析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 01:28 , Processed in 0.100977 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表