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.

Read the full article on tomcn.uk →

About the Author

I'm Tom Wang, an AI Developer & Fintech Developer — building AI agents, crypto payment infrastructure, and cross-border payout systems with Rust, Go, and TypeScript. Based in London, UK.

Currently open to new opportunities in fintech, crypto payments, and AI agent engineering.