很多文字版教程把 Reentrancy 攻击讲得抽象难懂,本份 Reentrancy 攻击图文教程则尝试用调用栈与状态变化的角度,把每一次重入的发生过程画出来。结合 Binance合约 与 Binance现货 实际业务,让你看完就明白要在哪里加锁。
一、调用栈视角的重入
想象一张图:横轴是时间,纵轴是合约调用栈。攻击者发起 withdraw,原合约转账触发回调,攻击合约再次调用 withdraw。此时调用栈上同时存在两个 withdraw 帧,但余额仅扣减一次。把这张图画在白板上,团队成员一下就能看懂。对 Binance量化交易 团队评估策略合约时,画一张类似的图能快速暴露风险。
二、状态变化时间线
再画一条横线表示状态变量 balance 的值。可以看到,转账之前 balance 仍是原始值,转账之后 balance 才更新。攻击者正是利用这段空窗期反复进入函数。把这条时间线和上面的调用栈叠加,重入的本质就一目了然。对接 Binance API接口 做链下记账时,也要保持时间线一致,避免链上链下出现错位。
三、CEI 修复后的图示
把状态变更前置之后,时间线上 balance 立即归零,再发起转账。即使回调进入 withdraw,他读到的 balance 已经是 0,自然无法盗取资金。这张图能直观说明 CEI 模式的威力。配合 Binance理财 类协议的复杂收益逻辑,CEI 仍然是首选方案。
四、加锁后的状态机
再画一个状态机:函数进入时锁打开,进入临界区,函数返回前锁关闭。重入尝试在锁打开状态下被阻断,状态机直接回到初始态。把这个图与 OpenZeppelin 的 ReentrancyGuard 实现对照,你会发现 Solidity 代码的每一行都对应图上的一个边。再叠加 pull 模式,让用户主动 claim,整体抗重入能力几乎拉满,对接 Binance跟单 的策略也能更稳定。
五、把图示变成团队语言
建议团队把这些图示打印出来贴在工位上,新人入职时第一周必须看图复述。每次代码 Review 都要求开发者用图来说明自己怎样避免重入。坚持下来,沟通成本会显著下降,代码质量也会同步提升。把 Reentrancy 攻击图文教程的内容变成团队语言,比单纯的文档更有持久力。