智能合约中的 TRX 转账
使用 transfer()、send() 或 call() 在 Solidity 合约内部转账 TRX。
前置阅读
持有 TRX 的智能合约能通过 Solidity 内置的地址成员函数向任意目标地址发送 TRX。常用选项有 transfer()、send() 和 call();选择哪一个,主要取决于接收方需要多少 Energy,以及失败时是否应立即回滚。
三种转账方式
transfer()
transfer()payable(receiver).transfer(amount);transfer() 固定向接收方转发 2,300 Energy。接收方拒收或执行失败时,transfer() 会自动 revert 整笔交易。对大多数用户发起的简单转账来说,这是更容易保持状态一致的默认选择。
send()
send()bool success = payable(receiver).send(amount);
require(success);send() 也只转发 2,300 Energy,但失败时不会自动回滚,只返回 false。如果使用 send(),必须检查返回值;否则转账失败后,后续状态更新仍可能继续执行。
call()
call()(bool success, ) = payable(receiver).call{value: amount}("");
require(success);call{value: ...}("") 默认转发剩余可用 Energy,适用于接收方合约确实需要在 receive() 或 fallback() 中执行更多逻辑的场景。它同样不会自动回滚,必须显式检查 success。
关于地址成员函数的完整语义,请参阅 Solidity 官方文档关于地址类型成员的章节。
示例:安全 TRX 转账
下面的合约提供一个仅限 owner 调用的 safeTransferTRX 函数:先检查接收方、转账金额和合约余额,再用 transfer() 发送 TRX。任何检查失败都会在状态变更前 revert。
pragma solidity 0.8.0;
contract SimpleTransfer {
address public owner;
// 允许合约接收 TRX
receive() external payable {}
fallback() external payable {}
event TRXTransferred(address indexed recipient, uint256 amount);
modifier onlyOwner() {
require(msg.sender == owner, "Caller is not the owner.");
_;
}
constructor() {
owner = msg.sender;
}
/**
* @dev 将指定数量的 TRX 转账给指定地址。
* @param recipient 接收方地址。
* @param amount 转账金额 (单位为 sun)。
*/
function safeTransferTRX(address payable recipient, uint256 amount) external onlyOwner {
require(recipient != address(0), "Recipient cannot be the zero address.");
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;
}
}开发要点
- 通过 TVM 调用向合约发送 TRX 时,对应的
receive()或fallback()必须标记为payable。当前主网也允许通过系统TransferContract直接向合约地址转入 TRX;该路径只增加合约的 TRX 余额,不执行这两个回调。 onlyOwner限制只有部署该合约的账户可以转出合约持有的 TRX。实际项目也可以改用角色权限或与业务状态绑定的提款规则。- 转账前拒绝零地址,避免不可恢复地销毁资金。
require应在转账前执行。检查失败时,交易会在状态变更前回滚。- Solidity
transfer()本身不会发出应用业务事件。需要追踪该调用时,应手动发出事件,例如TRXTransferred;如需完整统计合约入账,还要同时处理不执行回调的系统转账。
相关资源
- 编写与编译 Solidity — TRON 上的 Solidity 开发基础与流程
- FeeLimit 与能量成本 — 控制与支付智能合约执行的资源费用
- Solidity 官方文档地址成员说明 — 官方 Solidity 开发手册
Updated 26 days ago
