// 定义一个重入保护合约
contract ReentrancyGuarded {
// 定义一个布尔型的参数(重入锁),并初始化为false
bool reentrancyLock = false;
// 创建一个modifier(函数修改器)
modifier reentrancyGuard {
// 判断重入锁的状态,如果已经被使用(true),立即返回
if (reentrancyLock) {
revert();
}
// 进入到这一步,说明重入锁当前并未启用,那么设置为true,防止重入。
reentrancyLock = true;
// _; 这句的意思,即从这里开始,执行原方法的所有语句至结束。
_;
// 在这里,原方法已经执行完成,在这里恢复锁的状态。
reentrancyLock = false;
}
}
Solidity 中有三种方式进行转账,address.transfer、address.send、address.call。
Solidity 重入攻击是当我们用 address.call 的形式进行转账时,如果合约制定者没有指定 fallback 函数,有恶意的外部合约可能会调用当前合约的这个转账函数时 自定义一个 fallback,在 fallback 中再次转账,这样就陷入了不断取款的循环,直到我们的合约没有余额、Gas 不够、调用栈超出。
上面的合约代码,就利用modifier 来验证合约的重入调用。设置一个布尔型变量,每次调用的时候都验证当前是否为锁定状态。只有未锁定时,才会执行函数调用,函数结束时再次恢复锁的状态。虽然代码不多,但是非常精妙。
modifier 是个非常有用的设计,可以用来抽象出常用的一些验证方法,比如验证调用者身份,验证参数的值等等。一个函数可能须要作多个检查,那么咱们能够写多个modifier,调用时只需将每一个modifier以空格隔开。而检查顺序也就是modifier们的排列顺序。