Skip to content

These new docs are in beta. Please submit bugs to GitHub issues.


Anatomy of an Asset

Each Stellar asset has two characteristics: the asset code and the issuer. When you look up or interact with an asset on Stellar, you always use both to identify it.

Many Stellar tokens represent credits that can be redeemed for something outside the network—often fiat currency, but also bonds, carbon credits, gold, etc.—and since more than one organization can issue a credit representing the same underlying asset, asset codes often overlap. More than one company offers a USD token on Stellar, for instance.

However, the combination of asset code and issuer allows each asset to be uniquely identified: each USD token is offered by, and redeemable with, one specific issuer.

Asset Code

When you issue an asset, the first thing you do is choose an identifying code. Currently, there are two supported formats.

  • Alphanumeric 4-character maximum: Any characters from the set [a-z][A-Z][0-9] are allowed. The code can be shorter than 4 characters, but the trailing characters must all be empty.
  • Alphanumeric 12-character maximum: Any characters from the set [a-z][A-Z][0-9] are allowed. The code can be any number of characters from 5 to 12, but the trailing characters must all be empty.

Provided it falls into one of those two buckets, you can choose any asset code you like. That said, if you’re issuing a currency, you should use the appropriate ISO 4217 code, and if you’re issuing a stock or bond, the appropriate ISIN number. Doing so makes it easier for Stellar interfaces to properly display and sort your token in their listings, and allows potential token holders to understand, at a glance, what your token represents.

Issuer

There is no dedicated operation to create an asset on Stellar. Instead, assets are created with a payment operation: an issuing account makes a payment using the asset it’s issuing, and that payment actually creates the asset on the network.

The public key of the issuing account is linked on the ledger to the asset itself. Responsibility for and control over an asset resides with the issuing account, and since settings are stored at the account level on the ledger, the issuing account is where you use set_options operations to link to meta-information about an asset and set authorization flags.

Trustlines

Before an account can hold an asset another account issues, it has to establish something called a trustline, which is a persistent account-level ledger entry created with a change_trust operation.

A trustline is an explicit opt-in to hold a particular token, so it specifies both asset code and issuer. Each trustline increases an account’s minimum lumen balance by one base reserve — currently 0.5 XLM — and tracks the balance of the asset the account holds. Trustlines can also limit the amount of an asset an account can hold, though more often than not, account holders don’t set that limit: they simply turn the trustline on, which by default allows the maximum.

A trustline also tracks liabilities. Buying liabilities equal the total amount of the asset offered to buy aggregated over all offers owned by an account, and selling liabilities equal the total amount of the asset offered to sell aggregated over all offers owned by an account. A trustline must always have balance sufficiently large to satisfy its selling liabilities, and a balance sufficiently below its limit to accommodate its buying liabilities.

Representation

In Horizon, assets are represented in a JSON object:

Asset in Horizon
JSON
{
  "asset_code": "AstroDollar",
  "asset_issuer": "GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF",
  // `asset_type` is used to determine how asset data is stored.
  // It can be `native` (lumens), `credit_alphanum4`, or `credit_alphanum12`.
  "asset_type": "credit_alphanum12"
}

In the Stellar SDKs, they’re represented with the Asset class:

Asset in SDKs
var astroDollar = new StellarSdk.Asset(
  "AstroDollar",
  "GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF",
);

Amount Precision

Each asset amount is encoded as a signed 64-bit integer in the XDR structures that Stellar uses to encode transactions. The asset amount unit seen by end users is scaled down by a factor of ten million (10,000,000) to arrive at the native 64-bit integer representation.

For example, the integer amount value 25,123,456 equals 2.5123456 units of the asset. This scaling allows for seven decimal places of precision in human-friendly amount units.

The smallest non-zero amount unit is 0.0000001 (one ten-millionth) represented as an integer value of one. The largest amount unit possible is ((2^63)-1)/(10^7) (derived from max int64 scaled down) which is 922,337,203,685.4775807.

The numbers are represented as int64s. Amount values are stored as only signed integers to avoid bugs that arise from mixing signed and unsigned integers.

Relevance in Horizon and Stellar Client Libraries

In Horizon and client-side libraries such as js-stellar-sdk, the integer encoded value is abstracted away. Many APIs expect an amount in unit value (the scaled-up amount displayed to end users). Some programming languages (such as JavaScript) have problems with maintaining precision on a number amount. It is recommended to use “big number” libraries that can record arbitrary precision decimal numbers without a loss of precision.

Lumens (XLM)

Lumens (XLM) are the native currency of the Stellar network, and are the only asset that doesn’t require an issuer or a trustline. Every account is required to hold a minimum lumen balance, and all transaction fees are paid in lumens. The smallest unit of a lumen is a stroop, which is one ten-millionth of a lumen. For more on lumens, check out the Stellar.org explainer.

Last updated Jul. 13, 2020

Page Outline