Portal Community
A 1012 error is one assumption away. USDC and USDT carry 6 decimals; CFG and AIR carry 18. Encoding a 1,000 USDC repayment as if it were 18-decimal produces 1,000,000,000,000,000,000,000 instead of 1,000,000,000 — off by a factor of a trillion. This is why decimals is a required field on every conversion operation this node offers, with no default.

Known Currencies

These are the currencies this integration recognizes by symbol (used for reference/UI purposes — see the note below on how operations actually consume decimals):

SymbolNameDecimals
CFGCentrifuge18
AIRAltair18
USDCUSD Coin6
USDTTether USD6
DAIDai Stablecoin18
FRAXFrax18
wETHWrapped Ether18
GLMRGlimmer18

Native Tokens vs. Pool Currencies

CFG and AIR are the native tokens of the centrifuge and altair networks respectively — their decimals (18 for both) are fixed per network and returned as part of each network's descriptor (see Networks). Pool currencies (USDC, USDT, DAI, FRAX, wETH, GLMR) are the stablecoins and bridged assets that Centrifuge's real-world-asset pools are actually denominated in — a pool's repayments, NAV, and tranche values are in whatever currency that specific pool was configured with, not in CFG.

There is no automatic currency lookup yet. utility.convertUnits and utility.convertRate take decimals directly as a config field — they do not accept a currency symbol and resolve decimals for you. The caller (or the workflow author) is responsible for supplying the right value for whichever currency the amount is actually denominated in. See Roadmap for a planned currency-symbol convenience.

Base Units vs. Display Units

TermAccepted spellingsMeaning
Base unitsbase, planck, baseunitsThe smallest indivisible on-chain unit — what account.getBalance returns and what an extrinsic amount is denominated in.
Display unitsdisplayWhole tokens with a decimal fraction — what a human reads (e.g. "2.5 CFG").

Converting requires a decimals value in both directions: display → base multiplies by 10decimals (truncating any excess fraction); base → display divides by the same factor and trims trailing fractional zeros, returning plain "0" for a zero amount rather than "0.000…0".

Unknown currencies fail, they don't default. CentrifugeCurrencies.TryResolve(symbol) returns null for a symbol it doesn't recognize — callers must treat that as a reason to stop, not a reason to guess 18. The same philosophy runs through every conversion operation on this node.