Control Access to an Asset

When you issue an asset on Bantu, anyone can hold it by default. In general, that’s a good thing: easy access means better reach and better liquidity, and most of the time, issuers with KYC requirements can handle those when an asset moves onto or off of the network. Most fiat-backed token issuers, for instance, use the transfer server protocol specified in SEP-24 to decide whether to honor deposits and withdrawals rather than setting account-level flags. You can read about how to do that in the Enable Deposit and Withdrawal section.

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:

Authorization Required

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 using whatever means they see fit, and to approve trustlines if and only if the holders pass muster.

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

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

  • AUTHORIZED: This flag signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders.

  • AUTHORIZED_TO_MAINTAIN_LIABILITIES: This flag denotes limited authorization that allows an account to maintain current orders, but not to otherwise transact with the asset.

Authorization Revocable

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 transfer 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 allow_trust operation.

To use this setting, AUTHORIZATION REQUIRED must also be enabled.

Authorization Immutable

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

Example flow

To get a sense of how authorization flags work, 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-base 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 otherwise do anything 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 allow_trust operations:

  • Operation 1: Issuer uses AllowTrust to fully authorize account A, asset X

  • Operation 2: Issuer uses AllowTrust to fully authorize account B, asset X

  • Operation 3: Payment from A to B

  • Operation 4: Issuer uses AllowTrust to set account B, asset X to AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG state

  • Operation 5: Issuer uses AllowTrust 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

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

var StellarSdk = require("stellar-sdk");
var server = new StellarSdk.Server("https://expansion-testnet.bantu.network");

// 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);
  });

Last updated