Diffusc:可升级智能合约的差异模糊测试工具

Diffusc结合静态分析与差异模糊测试技术,可自动比较可升级智能合约的两个版本实现,在链上升级前发现行为差异。基于Slither和Echidna构建,支持标准模式和分叉模式测试。

可升级智能合约

基于委托调用(delegatecall)的代理模式是目前最常见的可升级智能合约(USC)实现方式。该模式中,代理合约存储实现合约地址,合约所有者可通过修改该地址升级逻辑。关键特性是在代理合约的fallback函数中使用delegatecall操作码,这使得所有未在代理中定义的函数调用都会被捕获。

与普通call操作码不同,delegatecall从目标合约获取函数代码但在代理合约上下文中执行,因此所有业务逻辑都使用代理的存储状态。这使得无需迁移状态即可更换实现合约。

差异模糊测试

模糊测试是一种通过随机生成输入来检测软件异常的安全分析技术。差异模糊测试是其变种,通过向两个相似实现提供相同输入,检测执行过程中的差异。

Echidna是最成熟的智能合约模糊测试工具,通常用于检测不变量违规。差异模糊测试采用外部测试方式,测试函数接收随机输入并调用两个实现的相同函数,然后断言结果应相同。

Diffusc实现

Diffusc是结合静态分析与差异模糊测试的工具链:

  1. 使用Slither静态分析识别升级影响的所有函数
  2. 生成用于部署和交互的包装合约(标准模式/分叉模式)
  3. 用户审查包装合约并补充必要信息
  4. 使用Echidna执行差异模糊测试

使用Slither进行版本差异分析

Diffusc的Slither扩展主要完成:

  • 比较两个USC实现生成差异,通过污点分析识别受影响的未修改代码
  • 识别代理合约存储实现地址的插槽

分析过程包括:

  1. 通过函数签名和变量列表比较识别新增/修改内容
  2. 使用SlithIR中间表示和控制流图对比检测语义变更
  3. 执行污点分析标记读取/写入相同存储变量的函数
  4. 跨合约污点分析处理外部调用情况

以Compound升级事件为例,分析显示21个状态变量和26个函数被污染,包括关键的compSupplyState映射。

为Echidna生成差异测试

Diffusc自动为每个目标函数生成包装方法,例如:

1
2
3
4
5
6
7
8
9
function TargetContract_balanceOf(address a) public virtual {
   hevm.prank(msg.sender);
   (bool successV1, bytes memory outputV1) = address(proxyV1).call(
       abi.encodeWithSelector(targetContractV1.balanceOf.selector, a)
   );
   // 相同调用针对V2实现
   assert(successV1 == successV2);
   assert((!successV1 && !successV2) || keccak256(outputV1) == keccak256(outputV2));
}

支持两种测试模式:

  • 标准模式:本地测试网部署所有合约
  • 分叉模式:从链上地址获取合约,使用两个分叉

实战案例:Compound漏洞复现

2021年9月,Compound升级引入的Comptroller合约漏洞导致约4000万美元COMP代币错误分配。Diffusc通过以下步骤复现:

  1. 在测试合约中包含升级函数
  2. 用户需自定义升级逻辑(调用_become函数)
  3. 标准模式下部署cToken合约并初始化市场
  4. 交易序列:mint() → upgradeV2() → claimComp()

分叉模式需额外设置测试合约为Comptroller管理员。两种模式均能在1小时内发现代币分配异常。

将Diffusc加入安全工具箱

Diffusc自动生成差异模糊测试合约,帮助开发者在升级前检测行为差异。虽然需要部分人工干预(如初始化逻辑和特殊前提条件),但作为安全工具链的重要补充,应在每次升级前使用。

特别感谢HEVM团队为分叉模式提供的支持,以及Slither静态分析工具的基础能力。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计