Deposit addresses and detection

How TON deposit addresses are derived, why the wallet contract version decides what address a mnemonic produces, why there is no memo to collect, and exactly when a deposit becomes a balance.

6 min readUpdated 3 August 2026deposits, addresses, wallet-version, bounceable, toncenter

Every ECO wallet holding TON gets its own TON account. That account is where the coins actually are — there is no pooling address, no shared contract and no sweep. This page covers how the address is produced, what form it takes, and the path from a transaction landing on-chain to a number changing in the platform.

How an address is derived

The first time a user opens the deposit page for TON, the platform generates a wallet for them:

  1. A 24-word TON mnemonic is generated and validated. TON mnemonics are not BIP-39 — they use TON's own scheme, and the platform generates and validates through TON's own library.

  2. The mnemonic is converted to an Ed25519 key pair.

  3. A wallet contract is created from the public key, and its address is the hash of that contract's initial state.

  4. The mnemonic, public key and private key are encrypted with the Ecosystem vault key and written to wallet_data as a single blob, alongside the address entry in the wallet's address map.

The encrypted blob is the only persisted copy of that key material. Nothing is written to disk in plaintext, and there is no export path. If the vault key is lost, every TON address on the install becomes unspendable.

The stored address entry also records the network the address was generated under, taken from TON_NETWORK at the time of generation.

Wallet versions, and why they matter

On TON, an address is derived from the public key and the code of the wallet contract that holds it. The same key produces a different address for every wallet version. The bundled library creates v3R1 wallets by default, and the platform does not override that.

Import a platform-generated mnemonic into a modern mobile wallet and it will show you a v4R2 or W5 address with a zero balance. The funds are not missing — they are at the v3R1 address, which that wallet is not showing you. Any manual recovery has to select the v3R1 wallet version explicitly.

This also explains the shape of the withdrawal path. When the platform signs a withdrawal it rebuilds the wallet from the stored key pair and the stored address, so the two can never drift apart. What it does not do is search other versions for funds, so anything sent to a v4 address derived from the same key is invisible to the platform.

Address format

The address handed to users is the user-friendly, non-bounceable form: 48 characters, beginning UQ on mainnet.

Non-bounceable is deliberate and it is the right choice for a deposit address. A TON account derived from a key does not exist on-chain until something deploys its contract, which for these wallets happens on their first outgoing transaction. A transfer sent to an uninitialised address with the bounceable flag set is returned to the sender; sent non-bounceable, it simply arrives and sits there. Users depositing to a brand-new platform address rely on that.

Two format details catch people out.

The address is emitted in standard base64, not URL-safe base64. That means it can contain + and / characters. It is a completely valid TON address and every wallet accepts it, but it is not the -/_ form most block explorers display. The two decode to the same account.

On a testnet install the address still carries the mainnet form. The test-only flag is not set when the address is rendered, so you get UQ… rather than the 0Q… you may expect. The underlying account is identical; only the display hint differs.

The withdrawal endpoint's character gate accepts letters, digits, -, _ and : only. Paste a standard-base64 TON address into it and you get 400 — Invalid address format. Address contains invalid characters or suspicious patterns. before any TON library sees the string.

The fix is a straight character swap: replace + with - and / with _. The result is the same address in URL-safe form and is accepted.

There is no memo, tag or comment

Deposits are attributed by destination address. The deposit parser reads the sender, the destination and the value; it never looks at the message body.

So: users sending from an exchange that offers a "memo", "comment" or "destination tag" field should leave it blank. Filling it in is harmless — it is ignored — but instructing users to enter one is not, because it implies a shared deposit address that this platform does not use.

If you have written support macros for other exchanges that require a comment on TON deposits, they do not apply here.

How a deposit is detected

Three things can find a TON deposit, and all of them do the same work.

The session monitor. While the user has the deposit page open, a WebSocket monitor polls their address once a minute. Each poll fetches the address's most recent 10 transactions.

The background scanner. Every address shown on a deposit page is registered in a Redis working set for 72 hours and re-scanned roughly every two minutes by a single-instance background loop. This is what catches "user sent funds then closed the tab". TON is rate-limited to 0.5 scans per second across the whole install, sized for anonymous Toncenter.

A page revisit. Opening the deposit page again restarts the session monitor and refreshes the 72-hour window.

For each transaction found, the platform:

  • skips it if a transaction row already carries that hash, or if the same hash was processed within the last 30 minutes;
  • skips it unless the transaction succeeded;
  • re-reads the transaction, converts both the expected and actual destination to the raw workchain:hex form and compares them, so the address format cannot cause a mismatch;
  • records a NATIVE DEPOSIT for the wallet with the value converted from nanotons.
Set to "false" to disable the background deposit scanner across every chain. Session monitors keep working; deposits arriving after a user closes the page will not be found until they reopen it.
Overrides the per-second scan budget for TON specifically. Raise it only if you run a paid Toncenter plan or your own endpoint.

TON deposits do not wait for confirmations

The confirmation watchdog that counts block depth for Bitcoin and the EVM chains treats TON — along with Solana, Tron and Monero — as already settled: if the recorded status is complete, it is confirmed. TON deposits are written as completed at detection.

That is a reasonable model for TON's finality, but be clear about what it means operationally: there is no confirmation counter to watch, the parsed transaction carries N/A for both confirmations and fee, and the credit happens on the first poll that sees the transaction rather than some minutes later.

Failure behaviour worth knowing

The monitor gives up. Ten consecutive polling errors and the session monitor stops for that address and logs it. Before that, it backs off — the interval doubles with each consecutive error up to sixteen times the base, so a dead endpoint is retried every sixteen minutes rather than every minute. It does not resume on its own; the user reopening the deposit page starts a fresh session.

Only the last ten transactions are visible per poll. An address that receives more than ten transactions between two polls loses the oldest ones from the window. In normal use this never happens — a per-user address receiving ten deposits in sixty seconds is not a real pattern — but it is the reason a bulk test script firing many small sends can appear to lose some.

A deposit is credited once. Deduplication is on the transaction hash, in the database, so the session monitor and the background scanner finding the same transaction cannot double-credit.