当前位置:网站首页>Solitidy - fallback 回退函数 - 2种触发执行方式
Solitidy - fallback 回退函数 - 2种触发执行方式
2022-06-30 05:29:00 【ling1998】
fallback简介
详情参考: 合约 — Solidity develop 文档
fallback函数是合约中的一个未命名函数,没有参数且没有返回值。
fallback执行条件:
- 如果在一个合约的调用中,没有其他函数与给定的函数标识符匹配时(或没有提供调用数据),fallback函数会被执行;
- 当合约收到以太币时,fallback函数会被执行。
以下针对2种执行方式进行示例展示,源码也可以参见:smartcontract/Fallback at main · tracyzhang1998/smartcontract · GitHub
执行条件1
如果在一个合约的调用中,没有其他函数与给定的函数标识符匹配时(或没有提供调用数据),fallback函数会被执行
测试合约代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
//基合约实现
contract TestFallback {
string message;
//构造函数,初始化状态变量message
constructor() {
message = "hello";
}
fallback() external {
message = "fallback";
}
//调用此合约中不存在的函数
function testFallback() external returns (bytes memory) {
// 调用不存在的函数getMsgNew()
bytes memory method = abi.encodeWithSignature("getMsgNew()");
(bool success, bytes memory returnData) = address(this).call(method);
require(success, "get fail");
return returnData;
}
//调用此合约中已存在函数,但是没有传递参数
function testFallbackWithNoParam() external returns (bytes memory) {
// 调用已存在的函数setMsg(),未传递参数
bytes memory method = abi.encodeWithSignature("setMsg()");
(bool success, bytes memory returnData) = address(this).call(method);
require(success, "set fail");
return returnData;
}
function getMsg() external view returns (string memory) {
return message;
}
function setMsg(string memory _message) external {
message = _message;
}
}
测试步骤与结果
(1)调用一个不存在的函数
0、部署合约,调用getMsg函数查看状态变量初始值为"hello"
1、调用函数testFallback,调用一个不存在的函数
2、调用getMsg函数查看状态变量已修改fallback函数中设置的"fallback"了

(2)调用一个已存在的函数但没传递参数
1、调用setMsg函数设置状态变量初始值为"hello"
2、调用函数testFallbackWithNoParam,调用一个已存在的函数但没传递参数
3、调用getMsg函数查看状态变量已修改fallback函数中设置的"fallback"了

执行条件2
当合约收到以太币时,fallback函数会被执行,为了接收以太币,fallback 函数必须标记为 payable。 如果不存在这样的函数,则合约不能通过常规交易接收以太币。
测试合约代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
// 包含fallback函数的合约,合约账户能够接收到其它合约转的以太币
contract TestFallback {
string message;
//构造函数,初始化状态变量message,同时可向合约账户存款
constructor() payable {
message = "hello";
}
//回退函数,能够为此合约账户接收以太币
fallback() external payable {
}
//存款,若部署时忘记存款,可直接调用此函数向合约账户存款
function deposit() external payable {
}
//发送以太
function sendEther(address _addr) external {
bool result = payable(_addr).send(2);
require(result, "send fail");
}
//查看合约账户余额
function getContractBalance() external view returns (uint256) {
return address(this).balance;
}
}
// 不包含fallback函数的合约
contract TestWithoutFallback {
//构造函数,初始化时可向合约账户存款
constructor() payable{
}
//存款,若部署时忘记存款,可直接调用此函数向合约账户存款
function deposit() external payable {
}
//发送以太
function sendEther(address _addr) external returns (bool) {
bool result = payable(_addr).send(2);
return result;
}
//查看合约账户余额
function getContractBalance() external view returns (uint256) {
return address(this).balance;
}
}
部署
部署时可直接向合约转20Wei,若部署时忘记转,则可使用合约中的deposit存款函数向合约转20Wei,如下图所示:

测试步骤与结果
(1)使用未含fallback合约函数向有fabllback合约发送以太
- 调用未含fallback合约(TestWithoutFallback)中的发送以太函数sendEther,参数为含fallback合约(TestFallback)地址,转2Wei;
- 查看TestWithoutFallback合约账户余额,发现少了2Wei,当前为18Wei了,证明转账成功;
- 查看TestFallback合约账户余额,发现多了2Wei,当前为22Wei,证明接收成功,合约账户能够接收以太,是因为合约中含有fallback函数(且为payable)。

(2)使用含fallback合约函数向未含fabllback合约发送以太
使用含fallback合约函数向未含fabllback合约发送以太,发现转账失败,报错了(如下图所示),即没有fallback函数的合约不能接收以币。官网文档解释如下:
一个没有定义 fallback 函数的合约,直接接收以太币(没有函数调用,即使用
send或transfer)会抛出一个异常, 并返还以太币(在 Solidity v0.4.0 之前行为会有所不同)。所以如果你想让你的合约接收以太币,必须实现 fallback 函数。

遇到的问题
在测试时,想通过查看状态变量message看是否发生调用fallback,在fallback函数中对message状态变量修改值,如下所示:
fallback() external payable {
message = "fallback";
}
测试使用未含fallback合约函数向有fabllback合约发送以太,如上面测试结果应该转账成功,但是此时转账会失败,如下图所示:

最终去除了fallback函数中设置message状态变量,函数体未包含任何内容,转账成功,与第(1)步测试结果相同。
fallback() external payable {
}
边栏推荐
- 《谁动了我的奶酪》读后感
- Records of some problems encountered during unity development (continuously updated)
- VFPBS在IIS下调用EXCEL遇到的Access is denied
- [notes] unity webgl input Chinese
- Unity3d- use animator and code to control task walking
- D. Big Brush
- Summary of common loss functions in pytorch
- Expansion method of unity scanning circle
- PyGame. Why can't I exit when I click X in the window? I can only exit when I return idle
- [typescript] defines the return value type of promise
猜你喜欢

The minecraft server address cannot be refreshed.

Unity shader flat shadow

Records of problems encountered in unity + hololens development

The file has been downloaded incorrectly!

Virtual and pure virtual destructions

Redistemplate common method summary

mmcv常用API介绍

9. naive Bayes

【LeetCode】Easy | 225. Using queue to realize stack (pure C manual tearing queue)

RedisTemplate 常用方法汇总
随机推荐
14x1.5cm竖向标签有点难,VFP调用BarTender来打印
如何写论文
mmcv常用API介绍
旋转框目标检测mmrotate v0.3.1 训练DOTA数据集(二)
How to judge the quality of network transformer? What symptom is network filter transformer broken?
Unity2019.3.8f1 development environment configuration of hololens2
pytorch中常用损失函数总结
Gradient clip in dqn
旋转框目标检测mmrotate v0.3.1 学习配置
The file has been downloaded incorrectly!
Question mark (?) in Cron expression Use of
Online assignment of C language program design in the 22nd spring of Western Polytechnic University
Intellj idea jars projects containing external lib to other project reference methods - jars
Terminal convenient SSH connection
Wechat applet training 2
UML tools
【LeetCode】Easy | 225. Using queue to realize stack (pure C manual tearing queue)
C. Divan and bitwise operations
2021-10-31
Bessel curve with n control points