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 transactionsTRC-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
Transferevent log emitted by the TRC-20 contract.
Structure
Each internal transaction has these fields:
| Proto # | Field | Description |
|---|---|---|
| 1 | hash | Unique 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 |
| 2 | caller_address | The contract that initiated the transfer |
| 3 | transferTo_address | The recipient |
| 4 | callValueInfo[] | List of value transfers — each entry has callValue (int64, sun amount) and tokenId (empty for TRX, the numeric TRC-10 token ID otherwise) |
| 5 | note | A short tag describing the call type. One of: call, create, or suicide (emitted by SELFDESTRUCT) |
| 6 | rejected | true if the parent transaction reverted |
| 7 | extra | Optional 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 defaultBy default, java-tron does not write internal transactions to local transaction receipts. To retain ordinary
call,create, andsuiciderecords on a self-hosted FullNode, setvm.saveInternalTx = trueinconfig.confand 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 enablevm.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:
| Aspect | TRON | Ethereum |
|---|---|---|
| Native asset transfers | TRX and TRC-10 | ETH only |
| Where they appear | internal_transactions array in receipt | Reconstructed from debug_traceTransaction |
| Token transfers (TRC-20 / ERC-20) | Track via event logs | Track via event logs |
APIs
| API | Description |
|---|---|
wallet/gettransactioninfobyid | Receipt with internal transactions |
wallet/triggerconstantcontract | Simulate a contract call without on-chain effects |
Related resources
- Transactions — Top-level transaction structure and lifecycle
- Signature validation — How transaction signatures are verified
- Listening to events — Track TRC-20 token movement
Updated 4 days ago