Event log
Define and emit events from TRON smart contracts; read and decode them off-chain through transaction logs.
Prerequisites
The event log is one of the most important features of the TRON Virtual Machine. Events let a contract emit specific binary data, which is recorded in the transaction's TransactionInfo. Event logs help developers confirm contract state changes, build off-chain indexers, and trigger UI updates without polling contract state. This page covers how to define events, how the TVM stores them, and how to decode an event log off-chain.
Defining and emitting events
In Solidity, declare an event with the event keyword and emit one with emit. Events can have any number of parameters; up to 3 of them can be marked indexed to make them searchable.
The TRC-20 Transfer event is the canonical example:
contract ExampleContractWithEvent {
event Transfer(address indexed from, address indexed to, uint256 value);
constructor() payable {}
function contractTransfer(address payable toAddress, uint256 amount) public {
toAddress.transfer(amount);
emit Transfer(msg.sender, toAddress, amount);
}
}event Transfer(...)declares an event with three parameters:from(sender),to(recipient), andvalue(amount).emit Transfer(msg.sender, toAddress, amount)writes the event to the log when the transfer succeeds.
Naming conventionSolidity convention is to capitalize event names (
Transfer) so they're distinguishable from the corresponding function names (transfer). The TVM does not enforce this — the convention is purely for readability.
How events are stored in TransactionInfo
TransactionInfoThe TVM uses the LOG opcode family to record event data. Logs appear in the log field of the transaction's TransactionInfo (retrievable via wallet/gettransactioninfobyid):
{
"id": "88c66d08f15b983183c7f7d23e3fafec0320bcc837d67957a8bda58d04ca53e1",
"log": [
{
"address": "a614f803b6fd780986a42c78ec9c7f77e6ded13c",
"topics": [
"ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"00000000000000000000000079309abcff2cf531070ca9222a1f72c4a5136874",
"00000000000000000000000081b64b1c09d448d25c9eeb3ee3b8f3348a694c96"
],
"data": "00000000000000000000000000000000000000000000000000000000b2d05e00"
}
]
}Each log entry has three parts:
| Field | What it contains |
|---|---|
address | the contract that emitted the event. To match the EVM format, TRON returns this without the 0x41 prefix — prepend 41 and Base58-encode it to get the TRON address |
topics | the event signature hash plus all indexed parameters. Stored separately so off-chain indexers can do prefix-scan filtering efficiently |
data | non-indexed parameters, ABI-encoded |
The split between topics and data exists because blockchain storage engines (LevelDB, RocksDB) optimize for prefix-scan queries. By placing indexed parameters in topics, off-chain indexers can quickly find "all Transfer events to address X" without reading the full event payload.
Decoding a log entry
To decode a log entry, you need the event's ABI. The ABI for the Transfer event above:
{
"anonymous": false,
"inputs": [
{"indexed": true, "name": "from", "type": "address"},
{"indexed": true, "name": "to", "type": "address"},
{"indexed": false, "name": "value", "type": "uint256"}
],
"name": "Transfer",
"type": "event"
}Walk through the log:
topics[0]=ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef— the event signature hash. Computed askeccak256("Transfer(address,address,uint256)"). Compare this against the hash of your event signature to confirm the entry is aTransferevent. You can compute the hash withtronweb.sha3. The signature string must contain no spaces —"Transfer(address, address, uint256)"(with spaces) would produce a different hash.topics[1]= firstindexedparameter,from. TRON addresses are stored with the0x41prefix stripped — take the last 40 hex chars, prepend41, and Base58-encode to get the TRON address.topics[2]= secondindexedparameter,to. Same decoding astopics[1].data= non-indexed parameters concatenated. Here there's only one (value), encoded as a 32-byte big-endian uint256.0xb2d05e00decodes to3,000,000,000in decimal.
If you have multiple non-indexed parameters, they are concatenated in declaration order following the ABI spec. See Parameter encoding and decoding for the full rules.
Anonymous eventsIf the event is declared
anonymous,topics[0]is omitted and indexed parameters start attopics[0]. Anonymous events save the 32-byte signature hash and can have up to 4 indexed parameters (instead of 3).
Patterns for off-chain consumption
Off-chain consumers of events fall into two main categories:
Polling for past events
Query past events through wallet/gettransactioninfobyid (single transaction) or by scanning blocks with wallet/getblockbynum and pulling logs from each transaction. This works for occasional queries but is inefficient for live monitoring.
Subscribing to live events
For live event streams, use TRON's event server endpoints (or a third-party indexer like TronGrid). TronWeb provides:
tronWeb.contract().at(contractAddress)
.Transfer()
.watch((err, event) => {
if (err) return console.error(err);
console.log('Transfer:', event);
});Subscriptions return events as they appear on-chain. For high-volume contracts (USDT, popular DEXes), use a dedicated event indexer rather than a public RPC.
Related resources
- Parameter encoding and decoding — ABI rules for
datafield decoding - Smart contract deployment and invocation —
wallet/gettransactioninfobyidquery - Interacting with contracts — call contract methods and read return values
- Opcodes —
LOG0throughLOG4opcode reference
Updated 9 days ago