Tron Blockchain

TRC-20 and native TRX custody for Bicrypto Ecosystem — per-user Tron addresses, TronGrid deposit detection, pooled withdrawals, and the energy and bandwidth accounting that decides whether a payout goes out at all.

4 min readUpdated 6 August 2026tron, trc20, trx, custody, energy, bandwidth

The Tron addon extends Ecosystem custody onto Tron. It adds one chain service to the install, and with it: per-user Tron addresses, deposit detection for native TRX and any TRC-20 token you import, and a withdrawal path that signs and broadcasts through TronWeb.

It is a small product with one large operational consequence. Tron does not charge fees the way every other chain in the platform does. There is no gas price paid out of the amount being sent and no fee-payer primitive that lets the platform sign on someone else's behalf. Instead every transaction consumes two metered resources — energy and bandwidth — and whichever account signs must own them or burn TRX to substitute for them.

That single fact is where Tron installs go wrong, and Energy and bandwidth is the page to read before you take a deposit.

What it requires

Requirement Why If it is missing
Bicrypto core Everything Nothing to extend
Ecosystem Wallets, the vault, deposit monitoring, the withdrawal queue The addon has no host — every code path it uses lives in Ecosystem
An activated Tron licence The chain service refuses to initialise without it Every Tron flow returns "TRON service not available"
A TronGrid API key (mainnet) Deposit polling The monitor rate-limits itself into shutdown
A Tron master wallet holding TRX Funding TRC-20 network fees TRC-20 withdrawals queue and never leave

This addon does not need ScyllaDB on its own account. Ecosystem does, for trading; Tron custody works without it.

What it actually adds

A chain service at backend/src/blockchains/tron.ts, discovered at runtime. Ecosystem imports it through a safe-import shim, so an install without the addon extracted simply reports the service as absent rather than crashing.

Per-user Tron addresses. Every ECO wallet that holds a Tron-backed currency gets a base58 address beginning with T, generated from a fresh BIP-39 mnemonic at m/44'/195'/0'/0/0 and encrypted with the Ecosystem vault key.

Deposit detection over the TronGrid REST API — a 30-second per-session poll while a user has the deposit page open, plus the shared background scanner for addresses whose owner has closed the tab.

Withdrawals for native TRX and TRC-20 tokens, with pooled sourcing when a user's own address does not physically hold the coins, and automatic TRX top-ups from the master wallet to cover the signer's energy and bandwidth.

It does not add token deployment. Ecosystem can deploy ERC20 contracts on EVM chains and SPL mints on Solana; on Tron you import an existing contract address. USDT on Tron is an import, not a deployment.

Two asset types, two different code paths

Almost every operational difference on this chain follows from which of these you are looking at.

Native TRX TRC-20 token
Registered as contractType: NATIVE contractType: PERMIT — the seeder rewrites anything else, and the deposit path ignores a hand-set NO_PERMIT
Deposit detected by TransferContract records on the account endpoint The TronGrid TRC-20 transfer endpoint, filtered by contract
Dust floor 0.001 TRX 1 / 10^(decimals − 3) — 0.001 for a 6-decimal token
Withdrawal signed by The user's own address only The user's address, or any custodial wallet holding the token
Network cost Bandwidth, burned from the amount's own account Energy plus bandwidth, funded by the master wallet
Master wallet involved No Yes — the payout cannot proceed without it

The right-hand column is the one that costs money to misunderstand. A Tron master wallet with no TRX does not break native TRX withdrawals at all; it silently stalls every TRC-20 payout on the install.

On EVM chains, a token that cannot delegate its own fee deposits into a shared custodial contract the platform deployed. Tron has no such mechanism in this product. Every Tron deposit — native or TRC-20, whatever contractType the token row carries — lands at the user's own address. Requesting a custodial wallet on Tron is not something the platform does.

So the seeder does not leave the value open. resolveContractType in seeders/20240402234741-ecosystemTokens.js rewrites every non-native TRON token to PERMIT before inserting it, and the same seeder runs an UPDATE that resets any TRON row whose contractType is neither NATIVE nor PERMIT. The admin import form applies no such rule, so you can still create a NO_PERMIT TRC-20 by hand — it deposits to the user's own address anyway, because usesCustodialDeposit() in ecosystem/utils/custody.ts refuses the custodial path for every chain in NON_CUSTODIAL_CHAINS and TRON is one of them, and the row is reset to PERMIT the next time the seeders run.

It is not ignored everywhere, which is why the row is still worth getting right. The deposit WebSocket's onClose reads contractType with no chain check to decide how long to keep the poller alive after the customer closes the tab: two minutes for NO_PERMIT, ten for anything else. A hand-flagged TRC-20 stops being watched sooner, for a reason that does not apply on this chain.

Do not read the deposit record as evidence either way. The Tron service stamps contractType: "NO_PERMIT" on every TRC-20 deposit it hands to storeAndBroadcastTransaction, whatever the token row says — so a correctly configured token still produces records that read NO_PERMIT. The custodial-address unlock that value would otherwise trigger is skipped only because the same line is guarded on a to field the Tron payload never sets.

Where to start

Install

Licence, the chain toggle, four environment variables, the master wallet and the diagnostics probe that names what is still missing.

Energy and bandwidth

How Tron charges for transactions, what the platform does about it, and why staking TRX is an operator decision the product does not make for you.

Deposits

Address derivation, the two detection endpoints, dust filtering, and why Tron deposits credit without a confirmation-depth wait.

Withdrawals

Pooled sourcing, the gas top-up, on-chain receipt confirmation, and every terminal state a Tron payout can reach.

Environment reference

Every variable the Tron service reads, what it defaults to, and which one takes the whole chain down when it is wrong.

Troubleshooting

Deposits not crediting, withdrawals stuck PENDING, OUT_OF_ENERGY, and the "private key not found" error on old wallets.

Three things to know on day zero

TRON_NETWORK is a total-outage variable. It accepts mainnet, shasta and nile. Any other value — including a typo, including mainnet-beta — makes the service throw during construction, and every Tron flow on the install is dead until it is corrected. This is not a degradation.

Tron is exempt from the token-network check. Ecosystem normally refuses to issue a deposit address when a token row's network disagrees with the chain's configured network. Tron is on the network-agnostic list, so that guard never fires here. A Tron address is textually valid on mainnet, Shasta and Nile alike — what changes is which chain the monitor watches. Switch TRON_NETWORK on a live install and existing addresses keep being issued while their deposits stop being seen.

The deposit monitor stops itself. After ten consecutive polling errors it logs and shuts down that address's loop rather than hammering TronGrid forever. Without TRON_API_KEY on mainnet, anonymous quota is enough to get there. This is the single most common cause of "deposits worked yesterday".