Understanding Hexadecimal to Decimal Conversion on the TRON Blockchain
When interacting with the TRON blockchain at the smart contract level, it's common to encounter values represented as long hexadecimal strings rather than human-readable numbers. This is especially true when reading TRC20 token balances directly from smart contracts using methods such as balanceOf(address).
For developers building wallets, payment gateways, blockchain explorers, or backend services, understanding how to convert these hexadecimal values into actual token balances is essential.
⏺ Why TRON Returns Hexadecimal Values
The TRON Virtual Machine (TVM), like the Ethereum Virtual Machine (EVM), follows the ABI (Application Binary Interface) specification for encoding return values. Integer values are returned as 256-bit unsigned integers (uint256), which are represented as 64-character hexadecimal strings.
00000000000000000000000000000000000000000000000000033199c048
Although this appears to be a very large number, most of the characters are simply leading zeros used to pad the value to 256 bits. The actual hexadecimal value is:
0x33199c048
⇄ Converting the Hexadecimal Value to Decimal
To convert the hexadecimal value into a decimal integer, PHP developers should avoid using hexdec() for large blockchain integers because it cannot safely handle 256-bit values. Instead, use the GMP extension:
<?php
$hex = "00000000000000000000000000000000000000000000000000000033199c048";
$decimal = gmp_strval(gmp_init($hex, 16));
echo $decimal; // Output: 13785718856
This number represents the token amount in its smallest divisible unit, not the user-visible token balance.
🔢 Understanding Token Decimals
Every TRC20 token defines a decimals property that specifies how many decimal places the token uses. For example:
| Token | Decimals |
| USDT (TRC20) | 6 |
| USDC (TRC20) | 6 |
| JST | 18 |
| SUN | 18 |
USDT on TRON uses 6 decimal places.
This means: 1 USDT = 1,000,000 smallest units. The blockchain stores balances in these smallest units to avoid floating-point precision issues.
🧮 Calculating the Actual Wallet Balance
Using the previous example:
- Hex: 000000000000000000000000000000000000000000000000000000000000033199c048
- Decimal: 13785718856
Since USDT has 6 decimals:
So the wallet actually contains:
🐘 PHP Example (BCMath)
<?php
$hex = "00000000000000000000000000000000000000000000000000000033199c048";
$rawBalance = gmp_strval(gmp_init($hex, 16));
$decimals = 6;
$balance = bcdiv($rawBalance, bcpow('10', (string)$decimals), $decimals);
echo $balance; // Output: 13785.718856
Using BCMath ensures that precision is maintained even for very large token balances.
⚠️ Why Not Use hexdec()?
PHP's built-in hexdec() function is suitable only for values that fit within the platform's integer or floating-point limits. Since TRON smart contracts return 256-bit integers, hexdec() can overflow or lose precision when handling large balances.
Using GMP or BCMath allows developers to work with arbitrarily large integers safely, making them the preferred choice for blockchain applications.
🔄 The Complete Conversion Process
When retrieving a TRC20 balance from the TRON blockchain, the process is always the same:
- Call the smart contract's
balanceOf(address)function. - Receive a 256-bit hexadecimal string.
- Convert the hexadecimal string to a decimal integer using GMP or another arbitrary-precision library.
- Retrieve or know the token's decimals value.
- Divide the decimal integer by 10decimals.
- Display the resulting value as the user's actual token balance.
For USDT (TRC20), this means dividing the raw integer by 1,000,000, since the token uses 6 decimal places.
📘 Conclusion
The hexadecimal values returned by TRON smart contracts are not directly human-readable balances. They are 256-bit encoded integers representing the token's smallest unit. Converting the value from hexadecimal to decimal is only the first step. To obtain the true wallet balance, the decimal value must then be adjusted according to the token's decimals setting.
For USDT on the TRON blockchain, this means dividing the converted decimal value by 106, transforming the raw blockchain data into the precise token balance that users expect to see. By using GMP or BCMath for arbitrary-precision arithmetic, developers can accurately process even the largest TRC20 token balances without risking overflow or loss of precision.