智能合约中的 TRX 转账

使用 transfer()、send() 或 call() 在 Solidity 合约内部转账 TRX。

📘

前置阅读

持有 TRX 的智能合约能通过 Solidity 内置的地址成员函数向任意目标地址发送 TRX。常用选项有 transfer()send()call();选择哪一个,主要取决于接收方需要多少 Energy,以及失败时是否应立即回滚。

三种转账方式

transfer()

payable(receiver).transfer(amount);

transfer() 固定向接收方转发 2,300 Energy。接收方拒收或执行失败时,transfer() 会自动 revert 整笔交易。对大多数用户发起的简单转账来说,这是更容易保持状态一致的默认选择。

send()

bool success = payable(receiver).send(amount);
require(success);

send() 也只转发 2,300 Energy,但失败时不会自动回滚,只返回 false。如果使用 send(),必须检查返回值;否则转账失败后,后续状态更新仍可能继续执行。

call()

(bool success, ) = payable(receiver).call{value: amount}("");
require(success);

call{value: ...}("") 默认转发剩余可用 Energy,适用于接收方合约确实需要在 receive()fallback() 中执行更多逻辑的场景。它同样不会自动回滚,必须显式检查 success

关于地址成员函数的完整语义,请参阅 Solidity 官方文档关于地址类型成员的章节


示例:安全 TRX 转账

下面的合约提供一个 safeTransferTRX 函数:先检查转账金额和合约余额,再用 transfer() 发送 TRX。任何检查失败都会在状态变更前 revert。

pragma solidity 0.8.0;

contract SimpleTransfer {
    // 允许合约接收 TRX
    receive() external payable {}
    fallback() external payable {}

    event TRXTransferred(address indexed recipient, uint256 amount);

    /**
     * @dev 将指定数量的 TRX 转账给指定地址。
     * @param recipient 接收方地址。
     * @param amount 转账金额 (单位为 sun)。
     */
    function safeTransferTRX(address payable recipient, uint256 amount) external {
        require(amount > 0, "Amount must be greater than zero.");
        require(address(this).balance >= amount, "Insufficient TRX balance in contract.");

        // transfer() 在接收方拒绝或执行失败时自动回滚交易。
        recipient.transfer(amount);

        emit TRXTransferred(recipient, amount);
    }

    /**
     * @dev 返回合约当前持有的 TRX 余额。
     */
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

开发要点

  • receive()fallback() 必须标记为 payable,合约才能接收并持有 TRX。
  • require 应在转账前执行。检查失败时,交易会在状态变更前回滚。
  • transfer() 本身不会抛出业务事件。需要被索引器或浏览器追踪时,应手动发出应用层事件,例如 TRXTransferred

相关资源