Official USDT and USDC contract addresses — and how to verify a deposit is the real token
The canonical Tether and Circle contracts KYTGate reads, why only those count, and how a look-alike token gets past a symbol-based check.
Anyone can deploy a token and name it USDT. Explorers show the symbol, wallets show the balance, and a deposit flow that keys off the symbol will credit it. The only defence is to check the contract address that emitted the transfer against the issuer's official one. This page lists the contracts KYTGate uses — generated from the same list the issuer-freeze check reads — and explains what "transaction integrity" means in practice.
On this page
The canonical contracts
Nine contracts across seven chains: USDT (Tether) on Ethereum, Tron and Avalanche; USDC (Circle) on Ethereum, Base, Arbitrum, Polygon, Avalanche and OP Mainnet.
| Chain | Token | Issuer | Contract address | Blacklist read | Explorer |
|---|---|---|---|---|---|
| Ethereum | USDT | Tether | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | isBlackListed(address) | Etherscan ↗ |
| Tron (TRC-20) | USDT | Tether | TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t | isBlackListed(address) | Tronscan ↗ |
| Avalanche C-Chain | USDT | Tether | 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7 | isBlackListed(address) | Snowtrace ↗ |
| Ethereum | USDC | Circle | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | isBlacklisted(address) | Etherscan ↗ |
| Base | USDC | Circle | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | isBlacklisted(address) | Basescan ↗ |
| Arbitrum One | USDC | Circle | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 | isBlacklisted(address) | Arbiscan ↗ |
| Polygon PoS | USDC | Circle | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 | isBlacklisted(address) | Polygonscan ↗ |
| Avalanche C-Chain | USDC | Circle | 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E | isBlacklisted(address) | Snowtrace ↗ |
| OP Mainnet | USDC | Circle | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 | isBlacklisted(address) | OP Etherscan ↗ |
These addresses come from the issuers' official publications and are configured in the product, never taken from user input. A change to this list is a code change, reviewed like any other. If an address here ever disagrees with the issuer's own page, the issuer's page wins — tell us.
How to verify a deposit is the real token
Read the transaction receipt and require a Transfer log emitted by the canonical contract, to your address, for the expected amount.
A stablecoin transfer is not a native coin movement; it is a contract call that emits a Transfer(from, to, value) event log. The log's emitting address is the token contract. A deposit is the real token only if that emitting address equals the canonical contract for that chain — not if the symbol matches, not if the name matches, and not if the explorer paints a logo on it.
KYTGate's transaction integrity check does exactly this for kind: "transfer" subjects: it fetches the receipt, confirms the transaction exists and succeeded, waits for the confirmation depth, finds the Transfer log emitted by the canonical contract, checks the recipient is yours and the amount is what the webhook claimed, and takes the log's from — not the transaction signer — as the address to screen. Any of these failing makes the transactionIntegrity coverage dimension fail and the decision REVIEW; it is never a credit.
Receipt log that passes integrity (Ethereum USDT) address: 0xdAC17F958D2ee523a2206206994597C13D831ec7 ← must equal the canonical contract topics[0]: Transfer(address,address,uint256) topics[1]: from → the address that gets screened topics[2]: to → must be your deposit address data: value → must match the claimed amount (6 decimals)
If you verify by hand: open the transaction on the explorer, go to the logs tab, and compare the log's address field character by character with the table above. Do not trust the token name column.
Common fake-token tricks
Same symbol, near-identical address, a real transfer of a worthless token, or a zero-value transfer from a look-alike sender.
- Same symbol, different contract. The simplest one: a token named "USDT" or "Tether USD" with 6 decimals, transferred to your deposit address. Every field except the contract address looks right.
- Address poisoning. The attacker sends dust from an address whose first and last characters match a legitimate counterparty, hoping a reviewer or an ops script copies it from history. Screening the log's from in full, not its abbreviation, defeats it.
- Real contract, wrong chain. Ethereum USDT's address is meaningless on another chain; a token deployed at the "same" address elsewhere is unrelated. Verification is per chain.
- Edited webhook. The transfer is real and canonical, but the amount or recipient in the notification was changed in transit, or the same hash is submitted twice. Integrity compares the chain to the claim, and the idempotency key stops the second credit.
- Transaction signer as sender. The transaction was sent by a contract or a relayer; the token actually came from another address inside it. Screening the signer screens the wrong party. The token log's from is what KYTGate screens.
Chains deliberately not covered
BNB Chain's Binance-Peg USDT/USDC have no issuer blacklist function; Solana has no comparable read in the current connector.
BNB Chain (BSC) is absent on purpose. The "USDT" and "USDC" there are Binance-Peg tokens issued by Binance, not by Tether or Circle, and their contracts expose no blacklist function. Pretending to read a freeze that does not exist would be a false sense of coverage, so on BSC the issuerFreeze dimension reports UNSUPPORTED and no read is made. The same reasoning applies to bridged variants on any chain.
Solana is screened for sanctions but has no issuer-freeze read in the current connector; the coverage matrix says so per screening rather than implying otherwise. Bitcoin has no stablecoins to read. The rule throughout is the same: the product reports what it actually checked, per dimension, and a NO_ADVERSE_SIGNAL on a dimension that did not run is not a result.
Questions
What is the official USDT contract address on Ethereum?
0xdAC17F958D2ee523a2206206994597C13D831ec7, issued by Tether. On Tron the TRC-20 USDT contract is TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t. Only these emit real USDT transfers on those chains; compare the emitting address of the Transfer log, not the token symbol.
How can I tell if a USDT deposit is fake?
Open the transaction on the explorer, look at the Transfer event log, and compare the log's emitting contract address with the official one for that chain, character by character. A matching symbol, name or logo proves nothing. KYTGate does this check automatically for transfer subjects and fails transaction integrity when the contract is not canonical.
Why does KYTGate not read a freeze on BNB Chain?
Because BSC USDT and USDC are Binance-Peg tokens whose contracts have no issuer blacklist function. There is nothing to read, so the issuerFreeze coverage dimension is reported as UNSUPPORTED on BSC instead of a made-up answer.
Which address gets sanctions-screened on a stablecoin deposit?
The from address in the canonical Transfer log — the token-level sender — not the transaction signer, which can be a contract or a relayer. Screening the signer would screen the wrong party.