Understanding TRC20 balances
USDT on the TRON blockchain is implemented as a TRC20 smart contract. Every wallet's token balance is stored inside the contract rather than in the wallet itself.
When you query a wallet balance, your application:
- Converts the wallet address into its hexadecimal representation.
- Encodes a call to the smart contract's
balanceOf(address)function. - Sends the request to a TRON node.
- Receives the balance as a 256-bit hexadecimal value.
- Converts the hexadecimal value to decimal.
- Divides by the token's decimal value (6 for USDT) to obtain the human-readable balance.
Prerequisites
- PHP 8.x or later
- The GMP extension (recommended for large integer calculations)
- A TRON Full Node or access to the TronGrid API
- The USDT TRC20 contract address
- The wallet address you want to check
1USDT Contract Address
The official USDT contract on the TRON blockchain is:
All balance queries are sent to this smart contract.
2Convert wallet address to hex
TRON smart contracts expect addresses in hexadecimal format rather than the familiar Base58 representation.
Example:
becomes something similar to:
The 41 prefix identifies the address as belonging to the TRON network.
3Encode the smart contract call
The TRC20 balanceOf(address) function has the following signature:
Its function selector is:
To build the parameter, remove the 41 prefix from the hexadecimal address, then left‑pad it with zeros until it reaches 64 hexadecimal characters.
This is the ABI‑encoded data sent to the smart contract.
4Call the TRON node
Send a POST request to the TRON API endpoint:
Example payload:
{
"owner_address":"YOUR_HEX_ADDRESS",
"contract_address":"USDT_CONTRACT_HEX",
"function_selector":"balanceOf(address)",
"parameter":"00000000000000000000000000000000000000000000000000000000000000",
"visible":false
}
Because this is a constant (read‑only) function, the transaction is executed locally by the node and does not consume bandwidth or TRX.
5Read the response
The node returns a response similar to:
{
"constant_result":["00000000000000000000000000000000000000000000000000000000000000"]
}
The value inside constant_result is the wallet balance encoded as a 256‑bit hexadecimal integer.
6Convert the hexadecimal balance
Using PHP's GMP extension:
$hex = $response['constant_result'][0];
$rawBalance = gmp_strval(gmp_init($hex, 16));
Result:
This is the balance in the token's smallest unit.
7Apply the token decimals
USDT uses 6 decimal places. Convert the raw balance:
$balance = bcdiv($rawBalance, '1000000', 6);
echo $balance;
Output:
This is the actual wallet balance displayed to the user.
Complete PHP example
$hex = $response['constant_result'][0];
$rawBalance = gmp_strval(gmp_init($hex, 16));
$balance = bcdiv($rawBalance, '1000000', 6);
echo "USDT Balance: " . $balance;
Example output:
Common mistakes
-
Using the Wallet API instead of the Contract
This only returns the native TRX balance. TRC20 tokens must always be queried through their smart contract.
-
Forgetting the token decimals
Raw Balance = 13785718856 → Displayed Balance = 13785.718856. Always divide by 106.
-
Using hexdec()
PHP's
hexdec()is not suitable for blockchain integers because TRON returns 256‑bit values. Use GMP or BCMath instead. -
Incorrect address encoding
Smart contracts expect hexadecimal addresses. Sending a Base58 wallet address directly will result in an error or an incorrect response..
Summary
Retrieving a USDT TRC20 balance from the TRON blockchain involves interacting directly with the USDT smart contract rather than querying the wallet itself. The process consists of encoding the balanceOf(address) function call, submitting it to a TRON node, converting the returned hexadecimal value into a decimal integer, and finally adjusting the result according to the token's decimal precision.
Although there are several steps involved, the process is straightforward once understood. By using PHP together with GMP and BCMath, developers can accurately retrieve and display USDT balances for wallets of any size without encountering integer overflow or precision issues. This approach is suitable for wallets, exchanges, payment processors, merchant platforms, and any application that needs reliable access to TRC20 token balances on the TRON blockchain.