重入攻击类型

  1. 单函数重入
  2. 跨函数重入
  3. 跨合约重入

单函数重入

跨函数重入

跨合约重入

避免重入攻击

互斥锁模式

uint private unlocked = 1;
    modifier lock() {
        require(unlocked == 1, 'UniswapV2: LOCKED');
        unlocked = 0;
        _;
        unlocked = 1;
    }

段代码定义了一个名为lock的函数修饰器(modifier)。由于这个修饰器是在智能合约内定义的,在智能合约内,可以把修饰器看成是一个包裹函数,它会包裹在被修饰的函数外面。

这个修饰器的主要作用就是在被修饰的函数执行时防止重入攻击。重入攻击指的是当一个智能合约在执行一个函数时,又会出发同一个或另一个合约的调用,如果不加控制地一直递归执行下去,可能会导致合约出现重复执行或者数据错误等问题。

具体来说,这个修饰器会首先判断变量unlocked的值是否为1,只有在unlocked等于1时,才允许调用被修饰的函数。然后,修饰器会将unlocked的值修改为0,并执行被修饰的函数(用_表示)。最后,被修饰的函数执行结束后,修饰器会再将unlocked的值修改为1,以便下次调用。

这种设计可以保证,在被修饰的函数执行期间,其他合约调用该合约的同一个函数时,都会被拒绝,从而避免了重入攻击的发生。

需要注意的是,在使用这个修饰器的时候,需要定义一个名为unlocked的全局变量,并且需要在智能合约的其他地方修改unlocked的值。这个变量是用来控制修饰器的执行行为的。

参考

https://www.aqniu.com/vendor/88702.html

https://paper.seebug.org/632/

https://www.cnblogs.com/wanghui-garcia/p/9580573.html solidity安全开发指南

https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls