坚固性 v0.6.0。回退功能。他们需要什么?

Solidity v0.6.0. Fallback functions. What are they needed for?

看了Solidity v0.6.0的文档docs,还是不明白fallback函数的意思。我读到它分为 2 个函数:fallback () external payable receive () external payable。他们是匿名的,不接受任何参数,在绝大多数情况下,receive () external payable 用于接收资金。您能否以我的代码为例,解释这些功能的一些用例,以便了解它们的所有功能,否则一切都在真空中,但我明白这是一个重要的概念?连receive () external payable函数的意思都不清楚,我在buyToken ()方法里调用了,直接在Remix里调用the buyToken ()干嘛还需要,绕过 receive () external payable 因为她不可见且匿名。

pragma solidity ^0.7.0;
    // SPDX-License-Identifier: MIT
    
    contract BuyToken {
      mapping(address => uint256) public balances;
      address payable wallet;
    
      event Purchase(
        address indexed buyer,
        uint256 amount
      );
    
      constructor(address payable _wallet) {
        wallet = _wallet;
      }
    
    
      fallback() external payable {
      }
    
    
      receive() external payable {
        buyToken();
      }
    
      function buyToken() public payable {
        balances[msg.sender] += 1;
        wallet.transfer(msg.value);
        emit Purchase(msg.sender, 1);
      }
    }

我不确定你的代码示例,但它是这样的:
后备函数 - 我认为here是一个很好的解释。因此,如果没有标记为 payable,如果合约收到没有数据的普通以太币,它将抛出异常。
外部应付款 - 这post很好地解释了外部。因此,与 public 相比,调用外部所需的 gas 更少。只有在您的示例中,将 buyToken() 从“public”更改为“外部”才有意义。据我所知,从外部调用 public 没有任何好处...

当发件人发送 ETH 到您的合约地址并且没有指定任何功能(即 tx 的 data 字段为空)时,receive() 被执行。

由于 receive() 只是调用 buyToken(),它会产生与用户直接执行 buyToken() 相同的一组操作。

但是其他合约可以对 receive() 函数进行不同的使用。简单银行合约示例:

pragma solidity ^0.8;

contract MyContract {
    mapping (address => uint256) public balances;

    receive() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint256 _amount) external {
        require(_amount <= balances[msg.sender], 'Insufficient balance');
        balances[msg.sender] -= _amount;
        payable(msg.sender).transfer(_amount);
    }
}

或者时间锁:

pragma solidity ^0.8;

contract MyContract {
    uint256 public constant unlockAfter = 1640995200; // 2022-01-01

    receive() external payable {
        // anyone can send funds to this contract
    }

    function withdraw() external {
        require(msg.sender == address(0x123), 'Not authorized');
        require(block.timestamp >= unlockAfter, 'Not unlocked yet');
        payable(msg.sender).transfer(address(this).balance);
    }
}

当函数签名(data 字段的前 4 个字节)与任何现有函数都不匹配时,将使用 fallback() 函数。

pragma solidity ^0.8;

contract MyContract {
    function foo() external {
        // executed when the `data` field starts with `0xc2985578`, the signature of `foo()`
    }
    
    fallback() external {
        // executed when the `data` field is empty or starts with an unknown function signature
    }
}

一个 Solidity 文件只能有一个带有关键字的未命名函数 payable,这被称为后备功能。这意味着以太坊区块链上的任何人都可以进行交互 使用此合约地址而不指定函数名称或输入 参数。

contract Fallback {
    function () payable {
    }
}
  • 这是一个没有参数的合同中的未命名函数,并且 return 数据。每次收到以太币时都会执行它。如果合同旨在接收以太币,则需要在合同中实施;除此以外, 将抛出异常并返回以太币。

  • 如果 合约中没有其他函数签名匹配。

  • 如果合同预计收到 ether,那么应使用 payable 修饰符声明回退函数。

  • 另一个用例是代理合约,它将传入请求路由到可升级的目标合约。代理合约中的回退函数实际上调用了目标合约的函数。

    function _fallback() internal virtual {
          _beforeFallback();
           // calling the target function code
          _delegate(_implementation());
      }