Internal transactions

Asset transfers triggered inside smart contract execution — visible to dApps, indexed by explorers, but not separate on-chain transactions.

When a smart contract executes, it can transfer TRX or TRC-10 tokens between accounts as part of its logic. These contract-triggered transfers are called internal transactions. They are not separate transactions on-chain — they are recorded as part of the receipt of the outer transaction that called the contract — but they are individually queryable through the API and are typically displayed by block explorers as a sub-list under the parent transaction.

This page covers what produces internal transactions, what their data fields look like, and how to query them.

📘

Prerequisites


What produces an internal transaction

An internal transaction is recorded whenever a smart contract executes a TRX or TRC-10 transfer to another account during its execution. This happens for:

  • Contract-to-account TRX transfers (e.g., address.transfer(amount))
  • Contract-to-contract TRX transfers (e.g., calling another contract with a value)
  • TRC-10 transfers triggered by the contract
  • Activation transfers (a transfer to an unactivated address triggers account creation)

A single outer transaction can produce zero, one, or many internal transactions, depending on the contract logic.

📘

TRC-20 transfers and internal transactions

TRC-20 token transfers are not internal transactions in this sense. TRC-20 is implemented entirely in contract storage — there is no native asset move. To track TRC-20 movement, parse the Transfer event log emitted by the TRC-20 contract.


Structure

Each internal transaction has these fields:

Proto #FieldDescription
1hashUnique identifier. For the root internal transaction this equals the parent transaction ID; child internal transactions use a derived hash (Keccak-256 of a payload that includes the parent hash and a per-call nonce) so each child has its own ID
2caller_addressThe contract that initiated the transfer
3transferTo_addressThe recipient
4callValueInfo[]List of value transfers — each entry has callValue (int64, sun amount) and tokenId (empty for TRX, the numeric TRC-10 token ID otherwise)
5noteA short tag describing the call type. One of: call, create, or suicide (emitted by SELFDESTRUCT)
6rejectedtrue if the parent transaction reverted
7extraOptional free-form string with extra context (set by the VM in specific code paths; often empty)

If the parent transaction reverts, all its internal transactions have rejected = true. The state changes do not take effect, but the internal transaction records are still emitted to make debugging traceable.


Where to find internal transactions

Internal transactions are part of the parent transaction's receipt. Query them via:

BASE_URL=https://api.trongrid.io   # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
POST ${BASE_URL}/wallet/gettransactioninfobyid
{ "value": "<txid>" }

The response includes an internal_transactions array if any were produced. Each entry follows the structure above.

For end-user display, TronScan shows internal transactions as a sub-list inside the parent transaction page.

📘

Internal transactions are not recorded by default

By default, java-tron does not write internal transactions to local transaction receipts. To retain ordinary call, create, and suicide records on a self-hosted FullNode, set vm.saveInternalTx = true in config.conf and restart the node. This setting applies only to transactions processed after the restart and does not backfill existing history. To retain extended records for Stake 2.0, voting, and similar operations, also enable vm.saveFeaturedInternalTx. Whether a hosted RPC returns internal transactions depends on the service provider's node configuration.


Comparison to Ethereum internal transactions

The TRON concept maps closely to Ethereum's "internal transactions": both refer to value transfers triggered by contract execution, both are not standalone transactions, and both are reconstructed from execution traces. The differences:

AspectTRONEthereum
Native asset transfersTRX and TRC-10ETH only
Where they appearinternal_transactions array in receiptReconstructed from debug_traceTransaction
Token transfers (TRC-20 / ERC-20)Track via event logsTrack via event logs

APIs

APIDescription
wallet/gettransactioninfobyidReceipt with internal transactions
wallet/triggerconstantcontractSimulate a contract call without on-chain effects

Related resources