Beginner

 

Assets Overview and Design consideration

This tutorial provides an overview of assets on the Stellar network, including the process of issuing assets and design considerations. Assets on Stellar can be tokenized and traded for various purposes, including cryptocurrencies, fiat currencies, NFTs, pool shares, or bonds and equity. Issuing an asset on Stellar is simple and requires no permission, but there are additional considerations such as asset information, compliance, and supply. The tutorial also covers stablecoins and how they are pegged to real-world assets, and the importance of treasury management. The tutorial also highlights the compliance requirements that asset issuers may need to follow and how Stellar’s built-in features can assist with this. It covers best practices for issuing assets by creating an issuing account and a distribution account for security and auditing purposes. The tutorial also touches on naming an asset and its identifying code, which is called the asset code.

Stellar’s core feature is issuing assets, where any asset can be transformed into a token and tracked, stored, and traded efficiently and inexpensively. Assets can range from cryptocurrencies (such as Bitcoin or Ethereum), fiat currencies (such as dollars or pesos), valuable tokens (such as NFTs), pool shares, bonds, and equity. Anyone can issue assets on Stellar, including banks, payment processors, money service businesses, for-profit enterprises, nonprofits, local communities, and individuals, as the process is self-service and doesn’t require permission.

The process of issuing an asset on Stellar is straightforward and requires only a few steps. However, you may need to consider additional factors depending on your specific use case, such as asset information dissemination, compliance, and supply. An asset’s unique identity on Stellar is defined by its asset code and issuer, with multiple organizations potentially issuing credit for the same asset. As a result, asset codes may overlap, with multiple companies issuing a USD token on Stellar, for example.

Stablecoins​

One major category of assets is the stablecoin. A stablecoin is a blockchain-based token whose value is tied to another asset, such as the US dollar, other fiat currencies, commodities like gold, or even cryptocurrencies. There are two types of stablecoin: 1) reserve-backed stablecoins that must have a mechanism for redeeming the asset backing them, and 2) algorithmic stablecoins that don’t have assets backing them and instead rely on an algorithm to control the stablecoin supply. When discussing stablecoins, our documentation will focus on reserve-backed stablecoins.

Reserve-backed stablecoins are pegged to a real-world asset at a 1:1 ratio. Because the underlying asset is maintained as collateral, users should be able to trade their stablecoin for the asset at any time. Asset reserves can be maintained by independent custodians and should be regularly audited.

Currently, one of Stellar’s most significant use cases is the tokenization of fiat currency for processes like cross-border payments. With anchors, users can connect Stellar tokens to existing rails that allow for the deposit of real-world assets in exchange for digital currency and vice versa. Learn more about anchors in our Anchors section.

Treasury management​

When issuing a reserve-backed stablecoin, you must set up its off-chain reserve, which securely stores the asset backing the stablecoin. When users wish to redeem their stablecoin, they can receive an equivalent amount of the underlying reserve asset from the issuer.

Compliance​

As an asset issuer, you may need to comply with regulatory requirements that vary based on jurisdiction. Stellar has built-in features that can help meet these requirements, such as:

Controlling access to an asset with flags

SEP-0008: Regulated Assets – regulated assets are assets that require an issuer’s approval (or a delegated third party’s approval) on a per-transaction basis. Check out this Stellar Ecosystem Proposal to learn how to implement regulated assets into your use case.

Issuing and distribution accounts​

It is best practice on the Stellar network to create two accounts when issuing an asset: 1) the issuing account and 2) the distribution account.

The issuing account creates (or mints) the asset on the network by executing a payment operation. The issuing account will always be linked to the asset’s identity. Any account wanting to hold the asset must first establish a trustline with the issuing account. Read about trustlines in our Trustlines section.

The distribution account is the first recipient of the issued asset and handles all other transactions.

Note that you can also issue an asset by creating an offer or liquidity pool deposit with the issuing account.

It is best practice to issue an asset by sending it from the issuing account to a distribution account for two main reasons: security and auditing.

Security​

The distribution account will be a hot account, meaning that some web service out there has direct access to sign its transactions.

For example, if the account you’re distributing from is also the issuing account and it is compromised by a malicious actor, the actor can now issue as much of the asset as they want. If the malicious actor redeems the newly issued tokens with an anchor service, the anchor may not have the liquidity to support the customer withdrawals. Stakes are lower if you use a distribution account- if the distribution account is compromised, you can freeze the account’s asset balance and start with a new distribution account without changing the issuing account.

Auditing​

Using a distribution account is better for auditing because an issuing account can’t actually hold a balance of its own asset. Sending an asset back to its issuing account burns (deletes) the asset. If you have a standing inventory of the issued asset in a separate account, it’s easier to track and can help with bookkeeping.

Naming an asset​

One thing you must decide when issuing an asset is what to call it. An asset code is the asset’s identifying code. There are three possible formats: Alphanumeric 4, Alphanumeric 12, and liquidity pool shares.

Learn about liquidity pool shares in the Liquidity Pool Encyclopedia Entry.

  • 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.
  • The pool share asset is defined by the liquidity pool identifier (PoolID), which in turn is defined by the two assets its reserves are composed of.

Provided it falls into one of these 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 what your token represents.

Controlling access to an asset with flags​

When you issue an asset on Stellar, anyone can hold it by default. In general, that’s a good thing: easy access means better reach and better liquidity. However, if you need to control access to an asset to comply with regulations (or for any other reason), you can easily do so by enabling flags on your issuing account.

Flags are created on the account level using a set_options operation. They can be set at any time in the life cycle of an asset, not just when you issue it.

Flag types​

The (0xn) next to each flag type denotes the bit settings for each flag.

Authorization Required (0x1)​

When AUTHORIZATION REQUIRED is enabled, an issuer must approve an account before that account can hold its asset. This setting allows issuers to vet potential token holders and to approve trustlines.

To allow access, the user creates a trustline, and the issuer approves it by changing the AUTHORIZE flag with the Set_Trust_Line_Flag operation.

There are two levels of authorization an asset issuer can grant using the Set_Trust_Line_Flag operation:

  • AUTHORIZED: signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders.
  • AUTHORIZED_TO_MAINTAIN_LIABILITIES: denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset.

 

Authorization Revocable (0x2)​

When AUTHORIZATION_REVOCABLE is enabled, an issuer can revoke an existing trustline’s authorization, thereby freezing the asset held by an account. Doing so prevents that account from transferring or trading the asset and cancels the account’s open orders for the asset.

AUTHORIZATION_REVOCABLE also allows an issuer to reduce authorization from complete to limited, which prevents the account from transferring or trading the asset but does not cancel the account’s open orders for the asset. This setting is useful for issuers of regulated assets who need to authorize transactions on a case-by-case basis to ensure each conforms to certain requirements.

All changes to asset authorization are performed with the Set Trustline Flags operation.

There are three levels of authorization an asset issuer can remove using the Set_Trust_Line_Flag operation:

  • AUTHORIZED: signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders.
  • AUTHORIZED_TO_MAINTAIN_LIABILITIES: denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset.
  • CLAWBACK_ENABLED: enables the issuing account to take back (burning) all of the asset. See our section on Clawbacks for more information.

 

Clawback Enabled (0x8)​

With the AUTHORIZATION_CLAWBACK_ENABLED flag set, any subsequent trustlines established with this account will have clawbacks enabled.

Read more about clawbacks in the Clawback Encyclopedia Entry.

Note that this flag requires that revocable is also set.

Authorization Immutable (0x4)​

With this setting, none of the other authorization flags (AUTHORIZATION REQUIRED, AUTHORIZATION REVOCABLE) can be set, and the issuing account can’t be merged. You set this flag to signal to potential token holders that your issuing account and its assets will persist on the ledger in an open and accessible state.

Set Trustline Flag operation​

The issuing account can configure various authorization and trustline flags for individual trustlines to an asset. The asset parameter is of the TrustLineAsset type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the asset type. If you are modifying a trustline to a pool share, this is the liquidity pool’s unique ID.

Example flow​

Let’s look at how an issuer of a regulated asset might use the AUTHORIZED_TO_MAINTAIN_LIABILITIES flag.

If the issuer wants to approve transactions on a case-by-case basis while allowing accounts to maintain offers, they can leave an account in the AUTHORIZED_TO_MAINTAIN_LIABILITIES state. That account can own offers but cannot do anything else with the asset.

To initiate a new operation, the holding account requests that the issuer approve and sign a transaction. Once the issuer inspects the operation and decides to approve it, they sandwich it between a set of operations, first granting authorization, then reducing it.

Here’s a payment from A to B sandwiched between set_trust_line_flags operations:

  • Operation 1: Issuer uses SetTrustLineFlags to fully authorize account A, asset X
  • Operation 2: Issuer uses SetTrustLineFlags to fully authorize account B, asset X
  • Operation 3: Payment from A to B
  • Operation 4: Issuer uses SetTrustLineFlags to set account B, asset X to AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG state
  • Operation 5: Issuer uses SetTrustLineFlags to set account A, asset X to AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG state

The authorization sandwich allows the issuer to inspect the specific payment and to grant authorization for it and it alone. Since operations bundled in a transaction are simultaneous, A and B are only authorized for the specific, pre-approved payment operation. Complete authorization does not extend beyond the specific transaction.

Sample code​

In the following code samples, proper error checking is omitted. However, you should always validate your results, as there are many ways that requests can fail. Refer to the Error Handling Encyclopedia Entry for tips on error management strategies.

The following example sets authorization to be both required and revocable:

  • JavaScript
var StellarSdk = require("stellar-sdk");
var server = new StellarSdk.Server("https://horizon-testnet.stellar.org");

// Keys for issuing account
var issuingKeys = StellarSdk.Keypair.fromSecret(
  "SCZANGBA5YHTNYVVV4C3U252E2B6P6F5T3U6MM63WBSBZATAQI3EBTQ4",
);

server
  .loadAccount(issuingKeys.publicKey())
  .then(function (issuer) {
    var transaction = new StellarSdk.TransactionBuilder(issuer, {
      fee: 100,
      networkPassphrase: StellarSdk.Networks.TESTNET,
    })
      .addOperation(
        StellarSdk.Operation.setOptions({
          setFlags: StellarSdk.AuthRevocableFlag | StellarSdk.AuthRequiredFlag,
        }),
      )
      // setTimeout is required for a transaction
      .setTimeout(100)
      .build();
    transaction.sign(issuingKeys);
    return server.submitTransaction(transaction);
  })
  .then(console.log)
  .catch(function (error) {
    console.error("Error!", error);
  });

 

Limiting the supply of an asset​

Warning! This section details how to lock your account with the purpose of limiting the supply of your issued asset. However, locking your account means you’ll never be able to do anything with it ever again- whether that’s adjusting signers, changing the home domain, claiming any held XLM, or any other operation. Your account will be completely frozen.

With that warning in mind:

It is possible to lock down the issuing account of an asset so that the asset’s supply is permanently fixed. To do this, set the issuing account’s master weight to 0 using the Set Options operation. This prevents the issuing account from being able to sign transactions and therefore, is unable to issue any more assets. Be sure to do this only after you’ve issued all desired assets to the distribution account.

Learn more about signature weights in the Signature and Multisig Encyclopedia Entry.

See how to do this in step five of the Issuing an Asset Tutorial.