坚固性 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());
}
看了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()); }