You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EIP-2535 Diamond智能合约惯用测试方法及Facet Mock方案

EIP-2535 Diamond模式下Facet单元测试隔离方案

目前没有专门针对Diamond模式的官方标准Mock方案,但基于hardhat+hardhat-deploy+smock2技术栈,可以完全实现无额外Solidity Mock合约的Facet独立测试,是目前行业内比较通用的做法,具体实现逻辑如下:

核心实现思路

跨Facet调用的本质是Diamond合约对自身地址发起delegatecall,路由到对应selector绑定的Facet实现地址执行。测试时不需要修改生产合约逻辑,只需要临时替换依赖Facet对应selector的路由指向,插入Mock逻辑即可。

具体操作步骤

  • 封装可复用的测试fixture:单元测试场景下,不要直接挂载全量Facet到Diamond实例,每个Facet的测试fixture仅部署Diamond核心逻辑、DiamondLoupe、DiamondCut等标准必需组件,加上当前被测Facet即可,不需要提前挂载依赖的其他Facet。
  • 基于smock2生成无代码Mock实例:直接用smock.fake()传入依赖Facet(比如例子里的FacetB)的ABI,就能在测试层生成Mock合约实例,不需要单独编写Solidity Mock合约。你可以自由预设Mock方法的返回值、设置调用次数/参数的断言规则。
  • 临时注入Mock路由:执行测试用例前,调用Diamond的diamondCut方法,把依赖Facet需要用到的方法selector,临时指向smock生成的Mock合约地址。这个操作仅在当前测试用例的EVM快照内生效,用例执行完后hardhat-deploy的fixture会自动回滚链上状态,不会污染其他测试场景。
  • 执行测试断言:触发被测Facet的目标方法后,直接用smock提供的断言能力,校验依赖Facet的方法是否被以预期参数调用即可,不需要执行依赖Facet的真实业务逻辑,完全实现关注点分离。

实践优化建议

  • 可以封装通用的测试工具函数,比如mockFacetCall,入参传Diamond实例、依赖Facet的ABI、要Mock的方法名、预设返回值,内部自动完成Mock实例生成、selector计算、临时diamondCut、断言绑定的逻辑,所有Facet的单元测试都可以复用,大幅减少重复测试代码。
  • 注意selector计算要直接用依赖Facet的合约接口实例的getSighash方法生成,不要手写selector字符串,避免参数类型不匹配导致的selector错误。
  • 全量Facet挂载的测试建议单独放到集成测试目录,和单元测试隔离,单元测试阶段始终保持最小依赖原则,只保留被测Facet+Mock依赖即可。

该方案完全适配hardhat-deploy的fixture快照机制,测试执行速度和普通单合约Mock测试没有明显差异,也不会对生产部署的合约逻辑产生任何侵入。

内容的提问来源于stack exchange,提问作者Doodloo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:51:30