If you receive USDT on TRON, there is one check worth doing before you release
fiat or goods: is the sender's address on Tether's blacklist?
A blacklisted address still shows its USDT balance in every wallet and explorer.
But any transfer from it reverts on-chain. If you accept funds that came
through a frozen address, or trade with someone whose wallet gets frozen
mid-deal, you find out the hard way.
Where the blacklist lives
The blacklist is not a separate database. It is state inside the USDT-TRC20
contract itself (TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t). The contract exposes a
read-only method, getBlackListStatus(address), which returns true for frozen
addresses. Tether can also call destroyBlackFunds on a blacklisted address,
which burns its balance.
Because the state lives in the token contract, the answer is chain-specific:
a TRON result tells you nothing about the same owner's Ethereum or TON wallets.
Fun fact to test your code with: the USDT contract address itself returns
true. Tether blacklisted its own contract, presumably so nobody can send
tokens to it by mistake.
Reading it with TronWeb
import { TronWeb } from "tronweb"; const USDT_TRC20 = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"; const tronWeb = new TronWeb({ fullHost: "https://api.trongrid.io" }); export async function isFrozen(address) { if (!tronWeb.isAddress(address)) throw new Error("Invalid TRON address"); tronWeb.setAddress(address); // constant calls need an owner address const usdt = await tronWeb.contract().at(USDT_TRC20); const result = await usdt.getBlackListStatus(address).call(); return result === true || result?.toString() === "1"; } A few production notes:
- Validate first. TRON addresses are Base58Check; reject anything that fails
isAddressbefore you call the network. - Use timeouts. Public TronGrid endpoints can be slow or rate-limited. Fail "unknown", not "clean".
- Cross-check. TronScan also indexes blacklist events. If the contract read and the index disagree, surface the disagreement instead of picking one.
- A clean result is a point-in-time fact. Addresses can be added after your check, so store the timestamp with the answer.
Blacklist ≠ OFAC ≠ "risky"
Three different questions often get mixed up:
- Tether blacklist: an issuer control inside the token contract (above).
- OFAC SDN: a US Treasury sanctions list that includes some TRON addresses. An address can be on one list and not the other.
- AML risk indicators: interpretation of exposure and flows. Useful context, but a model's opinion, not a fact.
Report them separately. Averaging them into one score hides the facts that
actually matter.
If you don't want to build it
I built TRON Checker
to do exactly this: contract read plus TronScan cross-check, exact OFAC match,
and explainable risk indicators. It's free for single checks, with no signup or
wallet connection. There is also an API
if you need it in a payment flow, and an
MCP server so AI agents can run
the same check (paid tiers accept x402).