Transferring TRX in smart contracts

Transfer TRX from inside a Solidity contract using transfer(), send(), or call().

📘

Prerequisites

A smart contract holding TRX can send TRX to any address by calling one of Solidity's built-in address member functions. The common options are transfer(), send(), and call(). Choose between them based on how much Energy the recipient needs and whether failure should revert immediately.

Three transfer methods

transfer()

payable(receiver).transfer(amount);

transfer() provides at most 2,300 Energy to the recipient contract's receive() or fallback() function. If the recipient rejects the transfer or execution fails, transfer() automatically reverts the whole transaction. For most simple user-initiated transfers, this is the easiest default for keeping state consistent.

send()

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

send() also provides at most 2,300 Energy, but it does not automatically revert on failure. It returns false. If you use send(), always check the return value; otherwise, later state updates may continue even though the transfer failed.

call()

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

call{value: ...}("") does not use the fixed 2,300 Energy limit. The Energy available to the recipient depends on the caller's available Energy at that point and the applicable protocol rules, so this method is suitable when receive() or fallback() needs to execute more logic. If call() fails, it returns success = false instead of automatically reverting the current transaction, so always check success; for example, use require(success) to revert when the transfer fails.

For the full semantic comparison, refer to the Solidity documentation on address members.


Example: safe TRX transfer

The contract below exposes an owner-only safeTransferTRX function. It validates the recipient, amount, and contract balance before transferring TRX, and reverts before the balance changes if a check fails.

pragma solidity 0.8.0;

contract SimpleTransfer {
    address public owner;

    // Allow the contract to receive 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;
    }

    // Safely transfer a specified amount of TRX to a given address.
    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() reverts the transaction automatically if the recipient rejects.
        recipient.transfer(amount);

        emit TRXTransferred(recipient, amount);
    }

    // Return the current TRX balance held by the contract.
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

Development notes

  • A TVM value call requires the matching receive() or fallback() function to be payable. A system TransferContract can also currently send TRX directly to a contract address on TRON Mainnet. This path only increases the contract's TRX balance and does not execute either callback.
  • onlyOwner restricts transfers to the account that deployed the contract. Production contracts can instead use role-based access control or withdrawal rules tied to application state.
  • Reject the zero address before transferring to prevent an irreversible loss of funds.
  • Run require checks before the transfer. If a check fails, the transaction reverts before any state change.
  • Solidity transfer() emits no application event on its own. Emit an event such as TRXTransferred when the call needs to be indexed, and also account for system transfers that bypass callbacks when reconstructing all contract deposits.

Related resources