在以太坊中,“纯转账”和“带数据的转账”是用户向合约地址发送 ETH 时的两种不同操作方式,核心区别在于是否附带<二进制数据>(即除了 ETH 金额外,是否携带额外信息)。

一、纯转账(无数据)

指用户仅向合约地址发送 ETH,不携带任何额外的二进制数据(msg.data 为空)。
这就像现实中“直接给对方现金,不附纸条”——只有金额,没有其他信息。

场景示例:
  • 在钱包(如 MetaMask)中,直接输入合约地址,填写 ETH 金额,点击“发送”,不调用任何函数。
  • 此时,交易的核心信息只有:发送方地址、接收方地址(合约)、ETH 金额,没有其他数据。
合约如何响应?
  • 若合约定义了 receive() external payable 函数,会优先触发 receive()(因为它专门处理纯转账)。
  • 若没有 receive(),但有 fallback() external payable 函数,则触发 fallback()。

二、带数据的转账(有数据)

指用户向合约地址发送 ETH 时,同时附带一段二进制数据(msg.data 不为空)。
这就像“给对方现金时,附一张纸条写着‘这是房租’”——除了金额,还有额外信息。

数据的作用:

这段数据通常是函数调用的信息,包含:

  • 要调用的合约函数签名(如 donate() 函数的哈希值);
  • 函数的参数(如捐款时备注的用户 ID 等)。

合约会通过解析这段数据,判断要执行哪个函数(例如“调用 donate(123) 函数”)。

场景示例:
  • 用户调用合约的某个函数(如 donate())并转账:此时交易除了 ETH 金额,还会携带 donate() 函数的签名和参数(作为数据)。
  • 用户调用一个不存在的函数(如合约中没有 invalidFunc(),但用户强行调用):此时交易携带的是 invalidFunc() 的签名和参数(无效数据),但仍属于“带数据的转账”。
合约如何响应?
  • 若数据对应的函数存在(如调用 donate() 且合约有该函数),则执行该函数(如果函数是 payable 的,可接收 ETH)。
  • 若数据对应的函数不存在(如调用无效函数),则触发 fallback() external payable 函数(因为 receive() 只处理无数据的情况)。

三、直观对比

类型核心特点msg.data(附加数据)触发的合约函数(优先级)
纯转账只发 ETH,无额外信息为空("")优先 receive() → 其次 fallback()(若 payable)
带数据的转账发 ETH + 附加二进制数据(如函数调用信息)不为空(有具体内容)优先匹配对应函数 → 否则 fallback()(若 payable)

四、用代码验证

通过 msg.data 变量可以直接查看转账是否带数据(msg.data 是 Solidity 内置变量,存储调用时的附加数据)。

示例合约:

contract TransferTest {
    event Log(string name, bytes data); // 记录数据是否存在

    // 处理纯转账(无数据)
    receive() external payable {
        emit Log("纯转账触发 receive()", msg.data); // msg.data 为空
    }

    // 处理带数据的转账
    fallback() external payable {
        emit Log("带数据触发 fallback()", msg.data); // msg.data 有值
    }

    // 显式函数(调用时带数据)
    function donate() external payable {
        emit Log("调用 donate() 带数据", msg.data); // msg.data 包含函数签名
    }
}
测试场景:
  1. 纯转账:直接向合约地址转 0.1 ETH(不调用任何函数)→ 触发 receive(),msg.data 为空。
  2. 调用 donate() 转账:调用 donate() 并转 0.1 ETH → 触发 donate(),msg.data 包含 donate() 的函数签名(如 0xa6f2ae3a)。
  3. 调用无效函数转账:调用合约中不存在的 invalidFunc() 并转 0.1 ETH → 触发 fallback(),msg.data 包含 invalidFunc() 的签名。

总结

  • 纯转账:只送 ETH,无附加信息(msg.data 空),对应“单纯打钱”。
  • 带数据的转账:送 ETH + 附加信息(msg.data 非空),对应“打钱时附带说明(如调用某个函数)”。

这两种方式决定了合约会触发 receive() 还是 fallback() 函数,是理解 Solidity 资金接收逻辑的关键。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐