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 isAddress before 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:

  1. Tether blacklist: an issuer control inside the token contract (above).
  2. OFAC SDN: a US Treasury sanctions list that includes some TRON addresses. An address can be on one list and not the other.
  3. 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).