开发者进阶进阶815 次阅读
交易模拟:上链前先预演一遍
模拟能在签名前告诉你交易会不会 revert、会改变哪些余额,也可能让你误以为它安全;本文讲清能力边界与正确用法。
#交易模拟#预演#RPC#用户体验#测试
一句话结论
模拟是在某个区块状态下把交易试跑一遍而不落链。它能回答「这笔交易会不会失败、会改哪些余额」,但不能回答「这笔交易安不安全」——这两件事被大量混淆。
模拟能发现什么
- 必然失败:调用会 revert、滑点不够、余额或授权不足、状态已被暂停。
- 状态变化预览:谁转给谁多少、授权额度变成多少、NFT 归属如何变化。把这份差异展示给用户,是对抗盲签最有效的界面设计。
- 权限校验:调用者不是管理员、角色不匹配这类问题,会在预演时暴露。
- Gas 消耗的量级:虽然不精确,但能看出这次操作是不是显著更贵。
大多数 RPC 节点都提供了「在最新状态上执行但不上链」的调用方式,前端可以借此在用户签名前拿到结果。
模拟不能发现什么
- 时序竞争:模拟时用的是当前状态,真实执行时状态已经被别人的交易改过。
- 价格变动:模拟用的是此刻的预言机读数,执行时可能已经偏移。
- 隐藏的后门与长期风险:你模拟的是一笔交易,不是这个合约未来所有可能的行为。
- 区块内的相互影响:抢跑、夹子、同一区块里的其他交易,模拟环境里并不存在。
- 模拟本身的失真:状态不完整、节点配置不同、有人刻意构造了对模拟友好的环境,都会让结果偏向乐观。
该怎么用
前端:签名前预演,把资产变化摊开给用户看;预演失败就给出人话解释,而不是让用户提交一笔注定失败的交易。
CI:在复刻的主网状态下跑关键调用,验证合约在真实数据下的行为,这比纯本地单元测试更接近现实。
上线前:把升级脚本、参数调整脚本完整预演一遍,确认效果符合预期再执行。
给你的教训
- 模拟通过不等于安全,它只是排除了「这笔交易必然失败」这一种情况。
- 把模拟结果当用户提示,而不是当校验闸门:差异要用可读方式呈现,让用户自己按下确认。
- 预演与真实执行的差异要提前想清楚,尤其是依赖价格与余额的操作。
- 别用模拟替代测试:单元测试、集成测试、复刻状态的端到端测试各有各的覆盖范围。