3分钟Solidity: 5.3 Fallback 回退

如需获取本内容的最新版本,请参见 Cyfrin.io 的Fallback(代码示例)

fallback函数是一种特殊函数,在以下情况下会被执行:

  • 调用了不存在的函数时
  • 以太币被直接发送到合约但 receive() 函数不存在 或 msg.data 不为空时

为了更好地理解 Solidity 在什么情况下会调用 receivefallback 函数,请参考下面的流程图:

scss 复制代码
                 send Ether
                      |
           msg.data is empty?
                /           \
            yes             no
             |                |
    receive() exists?     fallback()
        /        \
     yes          no
      |            |
  receive()     fallback()

当通过transfersend调用时,fallback函数有2300的gas限制。

solidity 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract Fallback {
    event Log(string func, uint256 gas);

    // 回退函数必须声明为外部函数。
    fallback() external payable {
        // 发送 / 转账(向该回退函数转发2300 gas)
        // 调用(转发这些所有gas)
        emit Log("fallback", gasleft());
    }

    // Receive 是 fallback 的一种变体,当 msg.data 为空时触发
    receive() external payable {
        emit Log("receive", gasleft());
    }

    // 用于检查该合约余额的辅助函数
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

contract SendToFallback {
    function transferToFallback(address payable _to) public payable {
        _to.transfer(msg.value);
    }

    function callFallback(address payable _to) public payable {
        (bool sent,) = _to.call{value: msg.value}("");
        require(sent, "以太币发送失败");
    }
}

Remix Lite 尝试一下

fallback 操作可选择性地接受 bytes 作为输入和输出

solidity 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

// TestFallbackInputOutput -> FallbackInputOutput -> Counter
contract FallbackInputOutput {
    address immutable target;

    constructor(address _target) {
        target = _target;
    }

    fallback(bytes calldata data) external payable returns (bytes memory) {
        (bool ok, bytes memory res) = target.call{value: msg.value}(data);
        require(ok, "call failed");
        return res;
    }
}

contract Counter {
    uint256 public count;

    function get() external view returns (uint256) {
        return count;
    }

    function inc() external returns (uint256) {
        count += 1;
        return count;
    }
}

contract TestFallbackInputOutput {
    event Log(bytes res);

    function test(address _fallback, bytes calldata data) external {
        (bool ok, bytes memory res) = _fallback.call(data);
        require(ok, "call failed");
        emit Log(res);
    }

    function getTestData() external pure returns (bytes memory, bytes memory) {
        return
            (abi.encodeCall(Counter.get, ()), abi.encodeCall(Counter.inc, ()));
    }
}

Remix Lite 尝试一下


END

相关推荐
devmoon15 小时前
Polkadot SDK Pallet 单元测试完整指南:从基础到实战
单元测试·web3·区块链·模块测试·polkadot
devmoon16 小时前
为 Pallet 搭建最小化 Mock Runtime 并编写单元测试环境
开发语言·单元测试·区块链·智能合约·polkadot
晚霞的不甘17 小时前
Flutter for OpenHarmony 打造沉浸式呼吸引导应用:用动画疗愈身心
服务器·网络·flutter·架构·区块链
devmoon18 小时前
Polkadot SDK 自定义 Pallet Benchmark 指南:生成并接入 Weight
开发语言·网络·数据库·web3·区块链·波卡
综合热讯18 小时前
股票融资融券交易时间限制一览与制度说明
大数据·人工智能·区块链
暴躁小师兄数据学院19 小时前
【WEB3.0零基础转行笔记】Solidity编程篇-第一讲:简易存储
web3·区块链·智能合约
devmoon1 天前
运行时(Runtime)是什么?为什么 Polkadot 的 Runtime 可以被“像搭积木一样”定制
开发语言·区块链·智能合约·polkadot·runtmie
暴躁小师兄数据学院1 天前
【WEB3.0零基础转行笔记】Rust编程篇-第一讲:课程简介
rust·web3·区块链·智能合约
devmoon1 天前
在 Paseo 测试网上获取 Coretime:On-demand 与 Bulk 的完整实操指南
开发语言·web3·区块链·测试用例·智能合约·solidity
unturn1 天前
solidity进阶
solidity