Send USDC to an address Circle has blacklisted and the transaction reverts. You keep the money and get an error string. Send USDT to an address Tether has blacklisted and the transaction succeeds, the balance lands, and from then on only Tether can move it.
I checked both against live mainnet state this morning, using addresses Tether froze on Tron at 23:32 UTC and on Ethereum at 23:35 UTC on 13 November 2026. Two of the guides ranking for "USDT blacklist check" and "can USDC be frozen" say a blacklisted address cannot receive USDT. The contract says otherwise, and if you run payouts, that difference decides who absorbs the loss.
Can USDC and USDT Be Frozen?
Yes. Both issuers can freeze any address on any chain where they control the token contract. What differs is which side of a transfer gets checked, who holds the key, and whether the issuer can destroy the frozen balance afterwards.
| USDC / EURC | USDT (Ethereum, Tron) | PYUSD | RLUSD | |
|---|---|---|---|---|
| Freeze call | blacklist(address) | addBlackList(address) | freeze(address) | pauseAccounts(...) |
| Who calls it | blacklister, a single EOA | Owner, a 3-of-6 multisig | ASSET_PROTECTION_ROLE | PAUSER_ROLE |
| Status getter | isBlacklisted | isBlackListed, getBlackListStatus | isFrozen | accountPaused |
| Recipient checked? | Yes | No | Yes | Yes |
| Destroy frozen balance? | No function exists | destroyBlackFunds | wipeFrozenAddress | clawback, no freeze needed |
USDC and EURC share one implementation contract (0x4350…02dd, FiatTokenV2_2), so everything below about USDC applies to EURC on Ethereum too.
How Does the USDC Blacklist Work?
Circle's FiatToken puts a notBlacklisted modifier on every function that moves value. transfer checks msg.sender and to. transferFrom checks the spender, from and to. EIP-3009's transferWithAuthorization checks from and to but not the relayer that submits it, which I covered in the gasless USDC comparison. Any hit reverts with Blacklistable: account is blacklisted.
Three implementation details matter for integrators.
The flag lives in the balance slot. Since v2.2,balanceAndBlacklistStates[account] stores the balance in the low 255 bits and the blacklist flag in bit 255. isBlacklisted is a shift, >> 255 == 1. Packing the two saves gas on every transfer, but anyone reading the raw slot, in a storage proof for example, gets the flag mixed into the balance and has to mask bit 255.
approve no longer checks the blacklist. Commit e5e7a2a (17 August 2023) removed the modifier from approve, permit and the allowance helpers. I confirmed it on mainnet: a blacklisted owner can still set an allowance, and anyone can approve a blacklisted spender. The allowance is useless, because transferFrom checks all three parties, but a monitoring rule that alerts on "approval by blacklisted address" will fire on things that are not attacks.
The contract blacklists itself. The v2.1 and v2.2 initialisers both call _blacklist(address(this)), so a transfer to the USDC contract address reverts. It is a cheap guard against a common fat-finger loss in ERC-20s.
There is no wipe, seize or burn-from function anywhere in the repository. burn only burns a minter's own balance. A Circle freeze leaves the balance in place until Circle reverses it, and reversals happen: the Tornado Cash pool addresses blacklisted at 16:15 UTC on 8 August 2022 were un-blacklisted at about 01:16 UTC on 22 March 2025, within a day of OFAC delisting Tornado Cash. I found no announcement of the removal, only the UnBlacklisted events. Circle's Access Denial Policy limits blocking to orders from US or French authorities, plus urgent law-enforcement and sanctions requests, and has a reversals clause.
How Does Tether Freeze USDT?
The Ethereum USDT contract is a non-proxy Solidity 0.4.18 contract from 2017. Its freeze logic is two lines:
function transfer(address _to, uint _value) public whenNotPaused {
require(!isBlackListed[msg.sender]);
// ...
}
function transferFrom(address _from, address _to, uint _value) public whenNotPaused {
require(!isBlackListed[_from]);
// ...
}
Nothing checks _to, and nothing checks the spender in transferFrom. The require has no message. Tron's TRC-20 USDT uses the same names and the same checks. The newer deployments do not change the pattern: Avalanche's TetherToken uses addToBlockedList and isBlocked, Arbitrum's USDT0 reverts with TetherToken: from is blocked, and neither inspects the recipient.
destroyBlackFunds(address) then sets the frozen balance to zero and cuts _totalSupply. Tether's model is freeze, burn, then reissue to the victim or the authority. On Ethereum that burn emits DestroyedBlackFunds and no Transfer event, so a balance indexer built only on Transfer logs drifts from balanceOf after every burn.
The owner is a Gnosis-style MultiSigWallet at 0xC6CD…a828 with six owners and required() = 3. A freeze is a submitTransaction followed by confirmations, and the pending transaction is public in between. A May 2025 AMLBot report found $78 million moved out during that gap between November 2017 and May 2025, $28.5 million on Ethereum and $49.6 million on Tron, with one case taking 44 minutes from submission to enforcement. Circle's blacklister is a single key, so a USDC freeze is one transaction with no visible proposal.
USDC vs USDT: What Happens When You Send to a Frozen Address?
I ran eth_call simulations against the latest Ethereum state, and the same calls through TronGrid's triggerconstantcontract on Tron. Nothing was broadcast. The senders were funded addresses on neither list. The targets were the Ronin bridge exploiter address (0x098B…2F96, blacklisted on USDC) and USDT addresses frozen the night before.
| Call | USDC (Ethereum) | USDT (Ethereum) | USDT (Tron) |
|---|---|---|---|
transfer, clean to clean | Succeeds | Succeeds, returns nothing | Succeeds, returns false |
transfer, clean to blacklisted | Reverts: Blacklistable: account is blacklisted | Succeeds | Succeeds |
transfer, blacklisted to clean | Reverts, same string | Reverts, empty revert data | Reverts, REVERT opcode executed |
approve by blacklisted owner | Succeeds | Succeeds | Not tested |
transfer to the token contract | Reverts, self-blacklisted | Not tested | Not tested |
Read the second row as a payout engine would. With USDC, a payout to a frozen address fails before anything moves and your ledger still holds the funds. With USDT, you get a successful receipt, reconciliation marks the payout settled, and the money now sits where only Tether can touch it. The block says the customer was paid. Recovering it is a conversation with Tether's compliance team, not a refund API.
The third row has its own traps. Ethereum USDT reverts a frozen sender with empty data, so an error mapper keyed on revert strings files it as "unknown". Tron USDT returned false from transfers that succeeded in my simulation, so code that checks the boolean and retries will pay twice. Confirm settlement from the Transfer event.
Which Stablecoins Can Be Frozen? PYUSD, RLUSD, DAI, USDS and USDe
PYUSD (PaxosTokenV2) checks both sides: if (_isAddrFrozen(to) || _isAddrFrozen(from)) revert AddressFrozen();. approve checks both parties too. The error is a custom error, selector 0x1fd1cc44, not a string, so decode it by selector. wipeFrozenAddress burns the balance and, unlike USDT, emits Transfer(addr, address(0), balance).
RLUSD pauses accounts per address and checks the recipient, the sender and from. Its clawback(from, value) burns from any address under CLAWBACKER_ROLE and does not require the account to be paused first. That is the broadest power of any EVM token here, matched only by PYUSD's permanent delegate on Solana.
DAI has no freeze. The contract is immutable and its wards can only mint. USDS has no freeze today, but it is UUPS-upgradeable, so governance could add one. USDe has no restrictions at all. Its staked form, sUSDe, has a blacklist and a redistributeLockedAmount that burns a fully restricted holder's balance and mints it elsewhere.
For US-regulated issuers these powers are no longer optional. The GENIUS Act, §4(a)(6)(B), lets a permitted issuer issue only if it "has the technological capability to comply" with lawful orders, and §2(16) defines those as orders to "seize, freeze, burn, or prevent the transfer" of its tokens. The statute requires the capability, not a particular contract design, which is why the OCC's final rule left the semantics alone.
Can Stablecoins Be Frozen on Solana?
Yes, but the unit is different. USDC's SPL mint has a freezeAuthority set. In SPL Token, FreezeAccount acts on a token account, not a wallet, and any instruction touching a frozen token account fails until it is thawed. A wallet can own several token accounts for one mint, so the issuer freezes accounts one at a time.
For a payer, the check is the state field of the exact token account you are crediting, usually the associated token account. A transfer into a frozen account fails, which is closer to USDC on EVM than to USDT.
PYUSD on Solana runs on Token-2022 with a permanentDelegate extension, and the delegate key is the same as the freeze authority. A permanent delegate can transfer or burn from any token account of that mint, so Paxos does not need a separate wipe instruction. The mint also carries a transfer-hook extension with no program set, and confidential transfers with auto-approval off.
How Much USDT and USDC Has Been Frozen in 2026?
The gap between the issuers is large and consistent across sources.
- AMLBot, 2023 to 2025: Tether blacklisted 7,268 addresses holding $3.29 billion, $1.75 billion of it on Tron. Circle blacklisted 372 addresses holding $109 million.
- BlockSec, calendar 2025: 4,163 USDT addresses frozen with $1.26 billion, 3,506 of them on Tron. Tether destroyed $698 million of it, 55.6%.
- BlockSec's live tracker listed 11,102 USDT addresses and $7.83 billion on the morning of 14 November 2026.
- Last night's batch: the four Ethereum addresses frozen at 23:35 UTC held 289,803 USDT between them.
How to Check if an Address Is Blacklisted Before a Payout
Each of these is a plain view call. Run it as close to signing as you can, not once at payee onboarding.
| Token | Chain | Getter | Selector | Freeze event |
|---|---|---|---|---|
| USDC, EURC | EVM | isBlacklisted(address) | 0xfe575a87 | Blacklisted(address indexed) |
| USDT | Ethereum, Tron | isBlackListed(address) | 0xe47d6060 | AddedBlackList(address) |
| USDT | Avalanche, USDT0 | isBlocked(address) | 0xfbac3951 | BlockPlaced(address indexed) |
| PYUSD | Ethereum | isFrozen(address) | 0xe5839836 | FreezeAddress(address indexed) |
| RLUSD | Ethereum | accountPaused(address) | 0xbc8c4b4f | AccountPaused(address) |
| USDC, PYUSD | Solana | token account state | n/a | n/a |
A raw call looks like this:
curl -s "$RPC_URL" -H 'content-type: application/json' -d '{
"jsonrpc":"2.0","id":1,"method":"eth_call",
"params":[{"to":"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"data":"0xfe575a87000000000000000000000000098b716b8aaf21512996dc57eb0615e2383e2f96"},
"latest"]}'
result ends in ...0001: blacklisted
Watch the event columns. USDC's Blacklisted indexes the address, so you can filter logs for your own wallets. Ethereum USDT's AddedBlackList does not, so you have to pull every event and decode the data field. Tron's USDT indexes it.
Pair the issuer check with your sanctions screening. They answer different questions: a sanctions list tells you whether you may pay someone, the token getter tells you whether the payment will be stranded.
Should Payment Platforms Prefer USDC Over USDT for Payouts?
My position: for payouts, yes, where the customer will accept it. USDC's recipient check means the sender keeps the money when something goes wrong. USDT's design puts that loss on the payer, and no amount of downstream reconciliation fixes a transfer that already settled.
I don't read USDT's missing recipient check as an oversight. It has survived from the 2017 contract into Avalanche and USDT0, and it suits a freeze, burn and reissue model, where funds arriving at a frozen address are funds Tether can later return to a victim. That serves law enforcement and hurts payers. I expect it to stay. Tether has had nine years and at least three contract generations to add a recipient check, and has not, which tells you it is a choice.
So supporting USDT is fine, but the pre-send check stops being hygiene and becomes the only control you have. On USDC a missed check costs you a failed transaction and some gas. On USDT it costs you the payout.
What This Means for Payment Engineers
1. Call the getter immediately before signing, per token and per chain, and block the payout on a hit. For USDT treat it as mandatory, since nothing after broadcast will save you.
2. Map every failure shape: USDC's string, PYUSD's 0x1fd1cc44, Avalanche USDT's Blocked: string and Ethereum USDT's empty revert. Each needs its own customer message.
3. Confirm settlement from logs, never from return values. Tron USDT returns false on success, and Ethereum USDT returns nothing.
4. Watch freeze events for your own addresses. Index Blacklisted by topic. For Ethereum USDT, decode every AddedBlackList. A frozen hot wallet should page someone within a block.
5. Reconcile burns separately. DestroyedBlackFunds changes balances with no Transfer, so a Transfer-only indexer will drift.
6. Never pool more than you can lose to one freeze. The address is the unit of freezing. If an issuer freezes an omnibus wallet, escrow or splitter contract over one depositor, every other balance in it freezes too. Per-customer deposit addresses and small, frequently swept hot wallets limit the damage.
7. Give frozen funds their own ledger account. They are neither lost nor available, and they may come back, as the Tornado Cash reversal shows.
I'm Tom Wang. If you take one thing from this, add a frozen-recipient case to your USDT payout tests this week. An eth_call against any address from last night's batch reproduces it in under a minute.