Skip to content

Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Create a security token

Important

This guide is meant to demonstrate what is technically possible on Algorand. It should not be used to determine if something is considered a security. Many of these features are applicable outside of regulatory use cases.

What are security tokens?

Security tokens, or restricted assets, are assets that require certain centralized control mechanisms. For example, if the asset you’re issuing is a U.S. security, you may need ways to comply with Know-Your-Customer (KYC) and Anti-Money Laundering (AML) regulations and this may take the form of having the ability to freeze or clawback those tokens in the case of fraud.

Having centralized control mechanisms on an asset may sound contradictory to everything we have talked about so far. Why use a decentralized blockchain if you want to exert some type of centralized control over an asset? To answer that question, revisit the blockchain basics section and remember that there are many properties (like low costs, efficiency, and composability) that offer significant improvements for some legacy systems.

Real estate example

Tokenization can lower the bar for entry and bring new investment opportunities to more people.

So how can we solve for this use case without encroaching on the promise of decentralization for the rest of the ecosystem? Algorand does this by offering several optional-to-use configuration settings on Algorand Standard Assets (ASAs). Specifically, when you create an ASA, you can specify a manager, reserve, freeze, and clawback address, OR you can leave any or all of them blank, which the protocol will interpret as immutable from that point forward. Embedding this configuration option within the broader decentralized and transparent Algorand ecosystem, offers users a choice to stick with assets that have no central control mechanisms, or to trust a specific issuer knowing exactly the type of control they have over the asset.

How to create security tokens

Creating security tokens is the same as creating NFTs or FTs, with the extra configuration settings specified.

txn = AssetConfigTxn(sender=account['pk'],
                    sp=params,
                    total=10000,                // Security tokens are typically fungible
                    default_frozen=False,
                    unit_name="RESTRICT",
                    asset_name="[email protected]",
                    manager=account['pk'],      // Address able to change mutable asset data
                    reserve=account['pk'],      // Address where non-minted assets will reside
                    freeze=account['pk'],       // Address able un/freeze the asset
                    clawback=account['pk'],     // Address able to remove asset from account
                    url="https://path/to/my/fractional/asset/metadata.json",
                    metadata_hash=json_metadata_hash,
                    decimals=2)                 // Security tokens typically have some precision
const creator = alice.addr;
const defaultFrozen = false;
const unitName = "RESTRICT";
const assetName = "[email protected]";
const url = "https://path/to/my/fractional/asset/metadata.json";   
const total = 10000; // Security tokens are typically fungible
const decimals = 2;  // Security tokens typically have some precision     
const managerAddr = account.addr;  // Address able to change mutable asset data
const reserveAddr = account.addr;  // Address where non-minted assets will reside
const freezeAddr = account.addr;   // Address able un/freeze the asset 
const clawbackAddr = account.addr; // Address able to remove asset from account
const txn = algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject({
    creator,
    total,
    decimals,
    assetName,
    unitName,
    assetURL: url,
    assetMetadataHash: metadata,
    defaultFrozen,
    freeze: freezeAddr,
    manager: managerAddr,
    clawback: clawbackAddr,
    reserve: reserveAddr,
    suggestedParams: params,
});
    String creator = aliceAccount.getAddress().toString();
    boolean defaultFrozen = false;
    String unitName = "RESTRICT";
    String assetName = "[email protected]";
    String url = "https://path/to/my/fractional/asset/metadata.json";
    BigInteger assetTotal = BigInteger.valueOf(10000); // Security tokens are typically fungible
    Integer decimals = 2;                              // Security tokens typically have some precision
    Address manager = account.getAddress();            // Address able to change mutable asset data
    Address reserve = account.getAddress();            // Address where non-minted assets will reside
    Address freeze = account.getAddress();             // Address able un/freeze the asset
    Address clawback = account.getAddress();           // Address able to remove asset from account
    Transaction tx = Transaction.AssetCreateTransactionBuilder()
            .sender(alice.getAddress().toString())
            .assetTotal(assetTotal)
            .assetDecimals(decimals)
            .assetUnitName(unitName)
            .assetName(assetName)
            .url(url)
            .metadataHash(assetMetadataHash)
            .manager(manager)
            .reserve(reserve)
            .freeze(freeze)
            .defaultFrozen(defaultFrozen)
            .clawback(clawback)
            .suggestedParams(params).build();
creator := account.Address.String()
  assetName := "[email protected]"
  unitName := "RESTRICT"
  assetURL := "https://path/to/my/fractional/asset/metadata.json"
  assetMetadataHash := metadataHash
  totalIssuance := uint64(10000)       // Security tokens are typically fungible
  decimals := uint32(2)                // Security tokens typically have some precision
  manager := account.Address.String()  // Address able to change mutable asset data
  reserve := account.Address.String()  // Address where non-minted assets will reside
  freeze := account.Address.String()   // Address able un/freeze the asset
  clawback := account.Address.String() // Address able to remove asset from account
  defaultFrozen := false
  note := []byte(nil)

  txn, err := transaction.MakeAssetCreateTxn(
    creator, note, txParams, totalIssuance, decimals,
    defaultFrozen, manager, reserve, freeze, clawback,
    unitName, assetName, assetURL, assetMetadataHash)

Run the accompanying code in your favorite SDK to see an example of using the freeze and clawback capabilities.