Transactions

Transaction structure, lifecycle, and the TAPOS replay protection mechanism on TRON.

A transaction is a cryptographically signed instruction from an account that updates the state of the TRON network. The simplest transaction transfers TRX from one account to another. Transactions can also create accounts, deploy and call smart contracts, stake TRX, and submit governance proposals.

To take effect, a transaction is broadcast across the network, validated, included in a block by a Super Representative, and then waits for the containing block to become solidified. This page covers the structure of a transaction, the four lifecycle phases, and the TAPOS mechanism that protects against replay on forks.

📘

Prerequisites


Transaction structure

A transaction has two top-level sections: raw_data (the signed payload) and signature (the proof of authorization).

{
  "raw_data": {
    "contract": [ /* one contract — see Transaction types below */ ],
    "ref_block_bytes": "c145",
    "ref_block_hash": "c56bd8a3b3341d9d",
    "expiration": 1646796363000,
    "data": "74657374",
    "timestamp": 1646796304152,
    "fee_limit": 10000000000
  },
  "signature": [
    "47b1f77b...8b0a1800"
  ]
}

The fields:

FieldDescription
raw_data.contractThe body of the transaction. The list contains exactly one contract today. Different transaction types use different contract bodies — see ContractType
raw_data.ref_block_bytesTAPOS — byte interval [6, 8) of the reference block's number, including byte 6 and excluding byte 8. See TAPOS
raw_data.ref_block_hashTAPOS — byte interval [8, 16) of the reference block's ID, including byte 8 and excluding byte 16
raw_data.expirationAfter this Unix timestamp (ms), the transaction is dropped instead of included. Default expiration is +60 seconds; max is 24 hours. See Expiration and timestamps below for the construction logic, config overrides, and the relationship with timestamp
raw_data.dataAn optional memo (hex bytes)
raw_data.timestampTransaction creation time. Optional — the on-chain timestamp is the block's timestamp. See Expiration and timestamps below
raw_data.fee_limitMaximum TRX (in sun) the network may burn for Energy on this transaction. Required for smart-contract calls. See FeeLimit & Energy cost for sizing, the Dynamic Energy Model, and per-tool examples
signatureThe sender's ECDSA signature(s) over SHA-256(protobuf_serialize(raw_data)). Each signature is 65 bytes on the wire: r (32) ‖ s (32) ‖ v (1, recovery byte 0 or 1). Multiple signatures appear when account permissions require multi-party authorization

Expiration and timestamps

A transaction carries two time fields in raw_data: expiration and timestamp. Only expiration controls whether the transaction is included — focus on that one. timestamp is a passive record of when the unsigned transaction was built and does not affect inclusion.

raw_data.expiration — the drop-by deadline

expiration is a hard cutoff in Unix milliseconds. After this timestamp the node drops the transaction instead of including it.

  • Default: 60 seconds beyond the latest block's timestamp.
  • Maximum: 24 hours.

When a Fullnode builds a transaction, it computes:

expiration = headBlockTimestamp + trx.expiration.timeInMilliseconds

The anchor is the head block's timestamp, not the node's wall-clock. This ties the deadline to chain progress: if the chain is keeping up, the transaction has roughly 60 seconds of "chain time" to land.

trx.expiration.timeInMilliseconds is set in the node's config.conf:

# trx.expiration.timeInMilliseconds = 60000

The line ships commented out, so most operators run with the built-in 60-second default.

How to extend or shorten

WhereMechanism
Node-wideStop the node, uncomment the line above in config.conf and set a new value in milliseconds (1 ms – 86,400,000 ms), then restart the node for the change to take effect. Every transaction the node builds afterward uses the new value.
Per-transactionMost mainstream SDKs let you override the expiration on a specific transaction — for example, TronWeb's extendExpiration. The 24-hour ceiling still applies at broadcast.

Typical reason to extend: large multi-signer flows where the unsigned transaction needs to circulate among signers for more than 60 s before broadcast.

raw_data.timestamp — for reference, not for enforcement

timestamp records the local wall-clock at the moment the node builds the unsigned transaction. It is not used to compute expiration (which is anchored to the head block, not to timestamp), and it is not the authoritative on-chain time for the transaction — that role belongs to the timestamp of the block that includes it. Treat timestamp as a debugging hint ("when did the client build this?"), not a control field. The two fields can drift apart by a few seconds in normal operation and by more under network congestion — don't write client logic that assumes expiration - timestamp == 60_000.

For local signing outside the node and the optional air-gapped workflow, see Signing transactions offline.


Transaction types

TRON supports many transaction types — TRX transfers, TRC-10 transfers, smart contract deployment and calls, staking, voting, and proposal submission. Each type uses a different contract body and a different API to construct it. Examples:

TypeContract bodyAPI
TRX transferTransferContractwallet/createtransaction
TRC-10 transferTransferAssetContractwallet/transferasset
Smart contract deployCreateSmartContractwallet/deploycontract
Smart contract callTriggerSmartContractwallet/triggersmartcontract
Stake TRXFreezeBalanceV2Contractwallet/freezebalancev2

For the full list of contract types, see Details of supported transaction types.

A transaction's serialized size is bounded — exceeding the chain's TRANSACTION_MAX_BYTE_SIZE limit causes the network to reject it as TooBigTransactionException. This matters mainly for large smart-contract deployments and transactions with deep multi-sig signature lists.


Transaction lifecycle

A transaction passes through four phases:

  1. Create and sign — Construct the raw_data payload locally and sign with the sender's private key.
  2. Broadcast and validate — Submit to a Fullnode. The node verifies the signature, checks Bandwidth and Energy, and adds the transaction to its mempool.
  3. Include in a block — When the next scheduled SR produces a block, it pulls transactions from the mempool in order, executes them, and includes them in the new block. The block is broadcast to the rest of the network.
  4. Solidify — A transaction is fully confirmed when the containing block is solidified — that is, when at least 19 distinct active SRs each have a latest successfully produced block number (latestBlockNum) greater than or equal to that block number. This typically takes about 1 minute. Until then, the transaction is in pending state and could theoretically be reorganized away in a fork.

For the solidification mechanism, see Consensus and DPoS — Block solidification.


TAPOS

TAPOS (Transaction As Proof Of Stake) is TRON's replay-protection mechanism. Each transaction is anchored to a recent block; if the chain forks and that block disappears from the canonical chain, the transaction also disappears, preventing replay on a malicious fork.

The transaction's ref_block_bytes and ref_block_hash fields together identify the reference block:

FieldSourceLength
ref_block_bytesByte interval [6, 8) of the reference block's number, including byte 6 and excluding byte 82 bytes
ref_block_hashByte interval [8, 16) of the reference block's ID, including byte 8 and excluding byte 168 bytes

By convention, libraries set the reference block to the most recent solidified block, so the transaction is anchored to a chain segment that the network has already confirmed.

The 2-byte ref_block_bytes field can address at most 65,536 distinct block numbers (the byte-space ceiling). In practice the validating node looks up reference blocks in its RecentBlockStore; if the reference block was forked away from the canonical chain, or if it has genuinely aged beyond the 65,536-block lookup window, validation fails with TaposException and the transaction is rejected. Anchor to a recent solidified block — typically a few seconds old — and broadcast within the transaction's expiration window.

For the SDK local-signing and air-gapped signing workflows, see Signing transactions offline.


Creating a transaction

Most workflows use TronWeb or another SDK to construct, sign, and broadcast a transaction. As an example, a TRX transfer:

const unsignedTxn = await tronWeb.transactionBuilder.sendTrx(
  "TVDGpn4h...wTppnkr",   // recipient
  100,                     // amount in sun
  "TNPeeaaF...8G1NYqeL"   // sender
);
const signedTxn = await tronWeb.trx.sign(unsignedTxn);
const result = await tronWeb.trx.sendRawTransaction(signedTxn);

For details on how the signing step works, see Signature validation. For local and air-gapped signing workflows, see Signing transactions offline.


APIs

APIDescription
wallet/createtransactionCreate a TRX transfer transaction
wallet/broadcasttransactionBroadcast a signed transaction
wallet/gettransactionbyidLook up a transaction by its ID
wallet/gettransactioninfobyidGet receipt: status, fee paid, logs

Related resources