If you have only ever integrated dollar stablecoins, EURC looks familiar: same issuer as USDC, a USDC-style smart contract, six decimals. But a euro stablecoin brings a few traps that dollar-coin code never had to handle. This post walks through them from a developer's point of view, with a small Python script that reads the token straight from Ethereum.
For the non-technical background (who issues it, what backs it, fees, where to buy it and how it's taxed), see this plain-English explainer on EURC, Circle's euro stablecoin.
What EURC is, in one paragraph
EURC is a euro-pegged token issued by Circle's French subsidiary as an e-money token under the EU's MiCA rules. Each token is meant to be worth €1 and redeemable 1:1, with reserves held as euro bank deposits. It pays holders no interest and lives on several chains, including Ethereum, Base, Solana, Avalanche and Stellar. If stablecoins are new to you, start with how stablecoins work.
Trap 1: "stable" does not mean "stable in your currency"
The most common bug is a units bug. Plenty of dashboards and wallets quietly assume every stablecoin equals one US dollar. EURC tracks the euro, so its USD value moves with EUR/USD every day.
Practical rules:
- Store balances in the token's own unit (EURC), not in USD.
- Convert to a display currency at read time, with a timestamped FX rate.
- Never sum USDC and EURC balances into one "stablecoin total" without converting first.
The same applies to accounting: for users outside the eurozone, swapping EURC back to their home currency can create a gain or loss purely from FX movement. Our guide to how stablecoins are taxed covers why that matters.
Trap 2: the name on-chain may not say "EURC"
The token used to be called "Euro Coin" with the ticker EUROC. Circle renamed it but kept the same contract addresses, so some explorers and apps still show the old name. That is exactly why you should never identify a token by its name or symbol: anyone can deploy a contract called "EURC". Identify it by contract address, taken from Circle's developer docs, and pin it in config per chain.
Trap 3: integers, decimals and per-chain supply
Like USDC, EURC on Ethereum uses 6 decimals, not 18. Hard-coding 18 is a classic bug that turns €5 into a rounding error. Read decimals() once, store it next to the address, and do arithmetic with integers or Decimal, never floats.
Also remember that supply is split across chains. The Ethereum contract only knows about Ethereum.
A dependency-free on-chain check
This script calls a public Ethereum RPC and reads the four standard ERC-20 views. It uses only the standard library. Double-check the address against Circle's docs before relying on it.
import json, urllib.request
from decimal import Decimal
RPC = "https://ethereum-rpc.publicnode.com"
EURC = "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c" # verify in Circle's docs
SELECTORS = {
"name": "0x06fdde03",
"symbol": "0x95d89b41",
"decimals": "0x313ce567",
"totalSupply": "0x18160ddd",
}
def eth_call(data):
body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "eth_call",
"params": [{"to": EURC, "data": data}, "latest"]}).encode()
req = urllib.request.Request(RPC, body, {"Content-Type": "application/json",
"User-Agent": "eurc-check/0.1"})
with urllib.request.urlopen(req, timeout=15) as r:
return json.load(r)["result"]
def decode_string(hexdata):
raw = bytes.fromhex(hexdata[2:])
length = int.from_bytes(raw[32:64], "big")
return raw[64:64 + length].decode()
name = decode_string(eth_call(SELECTORS["name"]))
symbol = decode_string(eth_call(SELECTORS["symbol"]))
decimals = int(eth_call(SELECTORS["decimals"]), 16)
supply_raw = int(eth_call(SELECTORS["totalSupply"]), 16)
supply = Decimal(supply_raw) / (Decimal(10) ** decimals)
print(f"{name} ({symbol}), decimals={decimals}")
print(f"Ethereum supply: {supply:,.2f} {symbol}")
When I ran it on November 12, 2026, it printed:
Euro Coin (EURC), decimals=6
Ethereum supply: 335,750,447.74 EURC
Two things to notice. The on-chain name() still returns "Euro Coin", which is Trap 2 in action. And the Ethereum supply is well below the roughly 471 million EURC that CoinGecko showed across all chains that day, because the rest lives on other networks. If you report "total supply", you need to sum each chain you support, or use an aggregator and say so.
Redemption is not universal
Under MiCA, holders have a right to redeem at par, and Circle offers a direct redemption path for retail holders. In practice it requires identity checks and an EEA bank account that receives SEPA payments. If your users are in the US, Canada or Australia, their realistic exit is selling on an exchange or swapping on a DEX, so liquidity and spreads matter more than the redemption promise. For a broader view of what can go wrong, see whether stablecoins are actually safe.
Key takeaways
- EURC is pegged to the euro; treat it as a separate currency in your data model.
- Identify tokens by contract address per chain, never by name or ticker.
- Read
decimals()(6 on Ethereum) and use integer orDecimalmath. - Per-chain supply is not total supply.
- Direct redemption needs an EEA bank account; most non-EU users exit via exchanges.
Read the full guide on NutshellCrypto
This post is for education only and is not financial advice.
This post was written with AI assistance.
Top comments (0)