Algorand Standard Asset (ASA)

Feature Overview

The Algorand platform is a general purpose economic exchange system which represents an extremely broad market. A given platform’s attractiveness and effectiveness as a means of economic exchange can be defined by the combination of what you can own and how you can transact.

Algorand Standard Assets represents Algorand’s ability to digitize any asset and have both it and its ownership represented on chain. These assets could be fungible (for example: currencies, stable coins, loyalty points, system credits, in-game points, etc) or non-fungible (for example: real estate, collectables, supply chain, in-game items, tickets, etc).  In addition, our functionality allows restrictions to be placed on the assets where needed (for example: securities, certifications, compliance, etc).

Algorand has implemented named assets as a truly layer 1 asset. This allows any asset created on Algorand to enjoy:

  • Increased security - New assets will enjoy the same security and safety as Algos, the native currency on Algorand

  • Inherent compatibility - Apps that support any Algorand asset will support all Algorand assets

  • High ease of use - Create your asset with a single transaction to the network

To test this feature out on BetaNet, see this page.

See here for SDK documentation: ASA SDK Usage

Step 1: Setup Accounts

Before getting into the details of how Standard Assets work we will create a default Wallet and add three accounts using the goal account and wallet new commands. 

goal wallet new MyWalletASA -d betanetdata
goal wallet -f MyWalletASA  -d betanetdata
goal account new -d betanetdata
goal account new -d betanetdata
goal account new -d betanetdata

We will also seed some assets into each account to account for transaction fees using the betanet dispenser.  Run this command and you should see something similar to the accounts listed below…

goal account list -d betanetdata
[offline] Unnamed-1 N23H6BKXXLF3LI42TVOMAQRL3RWMH3KHAC4CCWLK45X322CLJVGMLWU2LU 1000000 microAlgos
[offline] Unnamed-2 TKQZARURE2HYFQK2ORAYDSWH6YSVHRQKUVSMEOZLYCM3LVYYRIEHJ5I4XA 1000000 microAlgos
[offline] Unnamed-0 3T3ISYRTQNFKKERFSIT5KCVP5FYE4MNJCI42LZVIUPSJD7EK6KWBV7BZCI 1000000 microAlgos *Default

We can then use the goal account rename function to rename the accounts to AccountOne, AccountTwo and AccountThree

goal account rename Unnamed-0 AccountOne -d betanetdata
goal account rename Unnamed-1 AccountTwo -d betanetdata
goal account rename Unnamed-2 AccountThree -d betanetdata
[offline] AccountOne N23H6BKXXLF3LI42TVOMAQRL3RWMH3KHAC4CCWLK45X322CLJVGMLWU2LU 1000004 microAlgos
[offline] AccountTwo TKQZARURE2HYFQK2ORAYDSWH6YSVHRQKUVSMEOZLYCM3LVYYRIEHJ5I4XA 1000004 microAlgos
[offline] AccountThree 3T3ISYRTQNFKKERFSIT5KCVP5FYE4MNJCI42LZVIUPSJD7EK6KWBV7BZCI 1000004 microAlgos *Default

Step 2: Asset Issuance and Minting

Creating a new asset

To start with creating a new asset, you can use the goal asset command. The asset command has several sub commands to configure, create, destroy, freeze, send a new asset. There is also a sub command for getting the specific details of an asset. To create a new asset you can use the goal asset create command.  This command has many flags that can be used to do the initial configuration of your new asset. Creating an asset is done through a transaction on the Algorand network, so many of these flags are similar to the ones you use for standard transactions. The primary flags used for the actual asset are as follows:

Usage:
  goal asset create [flags]

Flags:
      --assetmetadatab64 string   base-64 encoded 32-byte commitment to asset metadata
      --asseturl string           URL where user can access more information about the asset (max 32 bytes)
      --creator string            Account address for creating an asset
      --defaultfrozen             Freeze or not freeze holdings by default
      --fee uint                  The transaction fee (automatically determined by default), in microAlgos
      --firstvalid uint           The first round where the transaction may be committed to the ledger
  -h, --help                      help for create
      --name string               Name for the entire asset
  -N, --no-wait                   Don't wait for transaction to commit
  -n, --note string               Note text (ignored if --noteb64 used also)
      --noteb64 string            Note (URL-base64 encoded)
  -o, --out string                Write transaction to this file
  -s, --sign                      Use with -o to indicate that the dumped transaction should be signed
      --total uint                Total amount of tokens for created asset
      --unitname string           Name for the unit of asset
      --validrounds uint          The number of rounds for which the transaction will be valid

The creator flag specifies the address of the asset creator. The transaction to create the asset must be signed by this account. The defaultfrozen flag specifies whether the asset is initially frozen, meaning transactions in this asset are currently not allowed for any account. The total flag specifies the maximum amount of this specific asset type. This number can not be changed once the asset is created. These assets are currently not issued and are considered non-minted at this point. The assetmetadatab64 field allows you to specify up to 32 bytes of data about the entire asset. You could use it to specify specific asset details like title deed location, court record, or specification location. The asseturl gives you an option to reference a link that includes more details of the asset off-chain. The unitname flag is used to give a specific name to the asset. This is an up to eight character name for the asset. As an example, if you want to create an asset named latinum with a maximum supply of one thousand assets you could use a command similar to the following:

goal asset create --creator AccountOne --total 1000 --unitname  latinum -d betanetdata

Or use the asseturl field to specify an off-chain url with more details;

goal asset create --creator AccountOne --total 1000 --unitname latinum --asseturl "https://path/to/my/asset/details" -d betanetdata

Once the transaction is completed you can list the account of the creator and see the newly created asset.

goal account list -d betanetdata

The output will show similar to the following.

[offline]	AccountOne	HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ	100002000 microAlgos	[created assets: 8 (1000 latinum)]
	                1000 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details)

This specifies that AccountOne has a created asset name latinum and the reserve is set to one thousand assets.  You can view all asset parameters using the goal asset info command.

goal asset info --creator AccountOne --asset latinum -d betanetdata
Asset ID:         8
Creator:          HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
Asset name:       
Unit name:        latinum
Maximum issue:    1000 latinum
Reserve amount:   1000 latinum
Issued:           0 latinum
Default frozen:   false
Manager address:  HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
Reserve address:  HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
Freeze address:   HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
Clawback address: HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ

You will notice in the command we referenced the asset by its name. You can also use the asset ID to reference the asset. In this case the latinum asset has an ID of 8. An Algorand account can create a maximum of 1000 assets.

Configuring Management of the asset

There are four capabilities inherent in a named asset:

  1. Manager Address - The manager account is the only account that can manipulate the configuration of a asset.
  2. Reserve Address - The reserve admin is the only account that can move assets from the reserve account (where the assets were created) which can also be thought of as “minting”.
  3. Freeze Address - The freezer account is the only account that is allowed to freeze or unfreeze specific accounts.  When an account is frozen it cannot send or receive transactions for that asset.
  4. Clawback Address - The clawback address is an account that is allowed to take assets from any account and give them to another account.

Once you have the asset created you can configure several addresses for the asset that each affect specific functionality for the asset. When first creating an asset all addresses will be set to the account that created the asset.  

--manager string        Manager account to issue the config transaction (defaults to creator)
    --new-clawback string   New clawback address
    --new-freezer string    New freeze address
    --new-manager string    New manager address
    --new-reserve string    New reserve address

The reserve account holds the balance of the coins considered not minted or not in circulation and is the account that signs transactions leaving the reserve.

If you do not wish specific features with the asset you are creating you can set the value of any of these addresses to "". This will, for the life of the new asset, prevent this feature from ever being used. For example, if you do not want your asset to ever be allowed to be taken back from a specific account you can specify a value "" as the clawback address. This can never be changed again. You can change one address for another, but as soon as you set the value to "", it can never be changed again.

If you change the reserve account it is also important to make sure that you accompany it with a transaction to transfer the existing assets in reserve to the new reserve account, else the assets currently in reserve will be listed as issued when inspecting the asset with the goal asset info command.

Changing the manager account to "" will not allow anything  in the asset to ever be changed again. The manager address is the administrative account and sole address for configuring all other addresses, so if this address is cleared the asset will be locked into a configuration.

Any account that wishes to accept and hold the new asset must opt-in with a special transaction that they sign. Until they do so transfers of this new asset to their account will fail.

This is discussed in the next section of this post. Accounts associated with the configuration of the asset do not require this (with the exception of the reserve account) as they do not necessarily have a balance of the new asset. The only configuration address that will require this setup is the reserve account. The reserve account is the account used to issue or mint new assets.

You can make address changes using the flags like the following:

goal asset config --creator AccountOne --asset latinum --manager AccountOne --new-manager AccountTwo  -d betanetdata

“Minting” and “Burning” Assets

Minting assets is as simple as moving units of your asset from (minting) and to (burning) the reserve account.  These units of your asset will no longer be counted in the issued total for your asset.

Step 3: Transacting with Algorand Standard Assets

Receiving a new Algorand Standard Asset

You can send assets to another account but before doing that the receiver has to authorize receiving your assets. They do this using the goal asset send command. The receiver needs to send zero amount of the newly created assets to their own account. For example:

goal asset send -a 0 --asset latinum  -f AccountTwo -t AccountTwo --creator AccountOne  -d betanetdata

After the transaction is committed you can list the accounts using the goal account list command.

[offline]	AccountOne	HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ	100002200 microAlgos	[created assets: 8 (1000 latinum)]
    1000 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details)
[offline]	AccountTwo	VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA	100004200 microAlgos
       0 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details)

The AccountTwo account is now ready to receive the new asset. You can see from the output that it currently has a balance of 0 latinum.

Sending Named Assets

You can now send assets from the creator account to AccountTwo using a command similar to the following:

goal asset send -a 10 --asset latinum -f AccountOne -t AccountTwo --creator AccountOne -d betanetdata

Listing the accounts should show that AccountTwo now has 10 latinum.

[offline]	AccountOne	HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ	100001300 microAlgos	[created assets: 8 (1000 latinum)]
     990 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details)
[offline]	AccountTwo	VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA	100004300 microAlgos
      10 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details)

You can now see 10 latinum are minted into production by using the goal asset info command

goal asset info --creator AccountOne --asset latinum -d betanetdata
Asset ID:         8
    Creator:          HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
    Asset name:       
    Unit name:        latinum
    Maximum issue:    1000 latinum
    Reserve amount:   990 latinum
    Issued:           10 latinum
    Default frozen:   false
    Manager address:  VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA
    Reserve address:  HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
    Freeze address:   HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ
    Clawback address: HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ

The  reserve has been decremented by 10 and the issued field is now 10.

Step 4: Manage Asset Capabilities

Freezing an account

Freezing an account prevents the account from sending or receiving a specific asset. This action can only be taken by the freezer account or by the creator when creating the asset.

goal asset freeze --freezer AccountOne --freeze=true --account AccountTwo --creator AccountOne --asset latinum -d betanetdata

Listing the accounts will show that account two is frozen:

[offline]	AccountTwo	VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA	100004400 microAlgos
    10 latinum  (creator HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, ID 8, url https://path/to/my/asset/details, frozen)

If someone tries to send a transaction of a specific asset to a frozen account they will get a message indicating that the account is frozen.

goal asset send -a 10 --asset latinum -f AccountOne -t AccountTwo --creator AccountOne -d betanetdata
Couldn't broadcast tx with algod: HTTP 400 Bad Request: TransactionPool.Remember: transaction QRQGGW3DZ272YSDMK5XLWMLUTUCPPU2KXA7CWSAVD3OZQINVLATA: asset frozen in recipient

If the frozen account tries to send the new asset it will also fail with a similar message.

To unfreeze an account you can use this command.

goal asset freeze --freezer AccountOne --freeze=false --account AccountTwo --creator AccountOne --asset latinum -d betanetdata

Revoking assets

The clawback address is the only address that can remove assets from an account. This functions similar to sending a assets, but you also specify the --clawback flag with the clawback address.

goal asset send -a 10 --asset latinum -f AccountTwo -t AccountOne --clawback AccountOne --creator AccountOne -d betanetdata

It is possible to also clawback assets from a frozen address. Do keep in mind that the transaction must be signed by the clawback account.

Destroying an Asset family

You can destroy a created asset family as long as you have the entire supply in the creator account. The manager key is responsible for signing this transaction. No other key can delete the asset family. For example, if we try to delete our previously created asset with the manager set to AccountOne:

goal asset destroy --creator AccountOne --manager AccountOne --asset latinum -d betanetdata 

We get the following error:

Couldn't broadcast tx with algod: HTTP 400 Bad Request: TransactionPool.Remember: transaction BABU35D6X3NT33NBSNEP5Z2TUYAQLQ5H64AMKO7GNFTRQLTK62DQ: transaction issued by HWYCB6YXZWPGXOJCXZQTK33BWLVBFQWVMDUWWKIHWNABAYLC3IKQ4SXRSQ, manager key VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA

We can delete the asset using the correct manager key as in the command below:

goal asset destroy --creator AccountOne --manager AccountTwo --asset latinum  -d betanetdata