W3
开发者进阶进阶815 次阅读

交易模拟:上链前先预演一遍

模拟能在签名前告诉你交易会不会 revert、会改变哪些余额,也可能让你误以为它安全;本文讲清能力边界与正确用法。

#交易模拟#预演#RPC#用户体验#测试

一句话结论

模拟是在某个区块状态下把交易试跑一遍而不落链。它能回答「这笔交易会不会失败、会改哪些余额」,但不能回答「这笔交易安不安全」——这两件事被大量混淆。

模拟能发现什么

  • 必然失败:调用会 revert、滑点不够、余额或授权不足、状态已被暂停。
  • 状态变化预览:谁转给谁多少、授权额度变成多少、NFT 归属如何变化。把这份差异展示给用户,是对抗盲签最有效的界面设计。
  • 权限校验:调用者不是管理员、角色不匹配这类问题,会在预演时暴露。
  • Gas 消耗的量级:虽然不精确,但能看出这次操作是不是显著更贵。

大多数 RPC 节点都提供了「在最新状态上执行但不上链」的调用方式,前端可以借此在用户签名前拿到结果。

模拟不能发现什么

  • 时序竞争:模拟时用的是当前状态,真实执行时状态已经被别人的交易改过。
  • 价格变动:模拟用的是此刻的预言机读数,执行时可能已经偏移。
  • 隐藏的后门与长期风险:你模拟的是一笔交易,不是这个合约未来所有可能的行为。
  • 区块内的相互影响:抢跑、夹子、同一区块里的其他交易,模拟环境里并不存在。
  • 模拟本身的失真:状态不完整、节点配置不同、有人刻意构造了对模拟友好的环境,都会让结果偏向乐观。

该怎么用

前端:签名前预演,把资产变化摊开给用户看;预演失败就给出人话解释,而不是让用户提交一笔注定失败的交易。

CI:在复刻的主网状态下跑关键调用,验证合约在真实数据下的行为,这比纯本地单元测试更接近现实。

上线前:把升级脚本、参数调整脚本完整预演一遍,确认效果符合预期再执行。

给你的教训

  • 模拟通过不等于安全,它只是排除了「这笔交易必然失败」这一种情况。
  • 把模拟结果当用户提示,而不是当校验闸门:差异要用可读方式呈现,让用户自己按下确认。
  • 预演与真实执行的差异要提前想清楚,尤其是依赖价格与余额的操作。
  • 别用模拟替代测试:单元测试、集成测试、复刻状态的端到端测试各有各的覆盖范围。

延伸阅读