Solidity v0.6.0.回退功能.他们需要做什么?



在阅读了Solidity v0.6.0文档后,我仍然不理解fallback函数的含义。我读到它被分为两个功能:fallback () external payablereceive () 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);
}
}

当发送者将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
}
}

我不确定你的代码示例,但它是这样的:
回退函数-我认为这是一个很好的解释。因此,如果没有标记应付,如果合同收到无数据的纯以太币,它将抛出异常。
应收账款-这篇文章很好地解释了外部。所以拨打外部电话比拨打公共电话花费更少。只有在您的示例中,才有意义将buyToken()从"public"external"帮助"。就我所知,从外部调用public没有任何好处。

回退函数由Ethereum Virtual Machine (EVM)自动调用,这就是为什么它们被标记为external。因为它不能显式调用,所以气体不能显式地发送给这个函数。相反,EVM为该功能提供了2,300 gas的固定津贴。如果gas成本超过2300,就会抛出异常。在部署契约之前测试回退函数的气体消耗是很重要的

contract Fallback {
fallback () external payable {
}
}
  • 没有参数和return数据。每次ether被接收时,它都会被执行。如果合同以接收以太为目的,则要求在合同内实施;否则,将抛出一个异常并返回ether。

更新在pragma solidity ^0.8.12;之后,fallback可以接收参数并有一个return语句

  • 如果您调用合约中不存在的函数,您的合约将回落到fallback()。它将调用fallback

  • 如果合同期望收到否则,则必须使用payable修饰符声明回退函数。

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

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

收到()

fallback函数在多个条件下被调用,这使得为每个条件编写代码变得困难。这就是添加receive的原因。receive只有在合约接收到以太币时才会被调用,所以fallback只有在没有函数签名的情况下才会被执行在合约中实现。

相关内容