One TON address, several formats: EQ, UQ and raw
Last updated:
At a glance
| Property | Value |
|---|---|
| Raw form | workchain:hex account ID, e.g. 0:… — no checksum |
| User-friendly form | 48 characters: flags + workchain + 32-byte account ID + CRC16 |
| Mainnet prefixes | EQ = bounceable, UQ = non-bounceable |
| Testnet prefixes | kQ = bounceable, 0Q = non-bounceable |
| Recommended for wallets | Non-bounceable, so transfers to an undeployed wallet are credited |
What you see
A wallet shows UQ…, an explorer shows EQ…, and an API response returns 0:… for what should be the same account. String comparisons fail, deposits look like they went to an unknown address, and lookups keyed on one format miss records stored in another.
Why this happens
TON's canonical address is the raw form: a workchain ID (0 for the basechain, -1 for the masterchain), a colon and the 256-bit account ID in hex. It has no checksum, so a typo is not detected. The user-friendly form packs one byte of flags, one byte of workchain and the 32-byte account ID, plus a two-byte CRC16 checksum, into a 48-character base64 or base64url string. The flags say whether the address is bounceable and whether it is meant for testnet — which is why the same account appears with different prefixes: EQ (bounceable) and UQ (non-bounceable) on mainnet, kQ and 0Q on testnet. The flag does not change the account; it tells the sender how to treat a message if the destination cannot accept it. Bounceable is the usual choice for smart contracts, so funds come back if the call fails; non-bounceable is recommended for wallets, so a transfer to a wallet that is not yet deployed is still credited.
What to do
- Normalise every address to the raw form (workchain + account ID) before comparing or using it as a database key.
- Keep the user-friendly string only for display and for sending, and choose its flag on purpose: non-bounceable for a wallet that may not be initialised, bounceable for contracts.
- Reject testnet-flagged addresses (kQ…, 0Q…) in mainnet flows, and the reverse.
- Validate the CRC16 checksum of user-friendly input; the raw form carries none, so double-check raw addresses from untrusted input.
When this is not our problem
Address encoding is defined by TON itself, not by whoever operates the node or API — Triport included — so the same account can reach you in any of these forms. Normalising addresses is an application-side step on any provider.
FAQ
- Are EQ and UQ addresses the same TON account?
- Yes, when they decode to the same workchain and account ID. The prefix only reflects the bounceable flag.
- Which TON address format should I store?
- Store the raw form (workchain and account ID) as the key, and render a user-friendly form for display.