The token catalogue
ChainOS credits deposits of a fixed, published set of tokens. The catalogue names each token, each chain it is deployed on, the contract address on that chain, and — the field everything else hangs off — the number of decimals that contract uses.
GET /v1/treasury/tokens
A deposit of a contract not in this list is not detected and not credited. That is a deliberate design choice rather than a limitation to work around: a chain carries thousands of tokens, most of them worthless, and many of them deliberately built to resemble one that is not.
Decimals are per chain, not per token
USDT is six decimals on Ethereum and eighteen on BNB Smart Chain. The same issuer, the same brand, the same ticker — a different precision.
This is why decimals appears on each deployment rather than once per token, and why you
should read it from the deployment you are actually crediting. Reading Ethereum's value
for a BNB Smart Chain deposit credits the customer one million-millionth of what they
sent. Reading it the other way credits them a trillion times too much.
A chain can be deliberately absent
Every token response carries unsupportedChains alongside its deployments, each with a
reason. A missing pair is always one or the other — listed as deployed, or listed as
deliberately absent with an explanation. There is no third category of "unknown".
{
"symbol": "USDC",
"deployments": [ { "chain": "eth", "decimals": 6, "monitored": true } ],
"unsupportedChains": [
{ "chain": "bsc", "reason": "Circle does not issue native USDC on BNB Smart Chain." }
]
}
Read unsupportedChains while you are designing, not after a request fails. It exists so
that a gap is something you find at integration time rather than through a 422 in
production.
Bridged and deprecated deployments
Two flags on a deployment matter more than they look:
deprecated— superseded, usually by a native issuance, and still monitored. Deposits to a superseded bridged token are real money and are credited. A deprecated deployment is one you should stop quoting to your users, not one you can stop watching.bridgeable— whether the token can be moved cross-chain. False for anything you could not redeem with its issuer. Bridging a third-party wrapper would hand you an asset nobody is obliged to honour, so the catalogue refuses to treat it as bridgeable however liquid it looks.
Polygon's bridged USDC.e was both, and was carried distinctly from native USDC until
registry v2 withdrew it — crediting one as the other is exactly the error the catalogue exists
to prevent, and the safest way not to make it is not to carry the wrapper at all.
Asking for a token that is not listed
POST /v1/treasury/token-requests
{ "chain": "eth", "contractAddress": "0x…", "symbol": "DAI", "decimals": 18 }
This records a request and puts the contract in front of a ChainOS administrator. It does not begin monitoring, and deposits of the token are not credited while it is under review. Sending funds to an address expecting them to appear will not work.
The symbol and decimals you send are recorded as your claim, not adopted as fact. The
contract is read on-chain, its decimals() is compared with what you declared, and a
second administrator approves the publication before anything changes. A mismatch between
your declaration and the chain is precisely what that review exists to catch — so state
the values as you have them, not as you think they should be.
Track a request with:
GET /v1/treasury/token-requests
The field to act on is monitored. It is false in every state but published:
state | monitored | What it means |
|---|---|---|
under_review | false | With an administrator. |
accepted | false | Approved into a pending change. Still not credited. |
published | true | In the catalogue. Deposits are now detected and credited. |
declined | false | Reviewed and declined. outcome carries the reason. |
Posting the same contract twice is a no-op — your account counts once either way.
When the catalogue changes
Publication is a versioned operation. GET /v1/treasury/routes returns the
registryVersion its answer came from, and a new version reaches every node within
seconds of being published. You do not need to do anything to pick it up, and a token
already in the catalogue never changes its contract address or decimals: a correction is
published as a new version, which is auditable, rather than edited in place, which is not.