Smart ASA | Algorand Developer Portal

Smart ASA

Abstract

A “Smart ASA” is an Algorand Standard Asset (ASA) controlled by a Smart Contract that exposes methods to create, configure, transfer, freeze, and destroy the asset.

This ARC defines the ABI interface of such a Smart Contract, the required metadata, and suggests a reference implementation.

Motivation

The Algorand Standard Asset (ASA) is an excellent building block for on-chain applications. It is battle-tested and widely supported by SDKs, wallets, and dApps.

However, the ASA lacks in flexibility and configurability. For instance, once issued, it can’t be re-configured (its unit name, decimals, maximum supply). Also, it is freely transferable (unless frozen). This prevents developers from specifying additional business logic to be checked while transferring it (think of royalties or vesting).

Enforcing transfer conditions requires freezing the asset and transferring it through a clawback operation — which results in a process that is opaque to users and wallets and a bad experience for the users.

The Smart ASA defined by this ARC extends the ASA to increase its expressiveness and its flexibility. By introducing this as a standard, both developers, users (marketplaces, wallets, dApps, etc.) and SDKs can confidently and consistently recognize Smart ASAs and adjust their flows and user experiences accordingly.

Specification

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

The following sections describe:

ABI Interface

The ABI interface specified here draws inspiration from the transaction reference of an Algorand Standard Asset (ASA).

To provide a unified and familiar interface between the Algorand Standard Asset and the Smart ASA, method names and parameters have been adapted to the ABI types but left otherwise unchanged.

Asset Creation

{
  "name": "asset_create",
  "args": [
    { "type": "uint64", "name": "total" },
    { "type": "uint32", "name": "decimals" },
    { "type": "bool", "name": "default_frozen" },
    { "type": "string", "name": "unit_name" },
    { "type": "string", "name": "name" },
    { "type": "string", "name": "url" },
    { "type": "byte[]", "name": "metadata_hash" },
    { "type": "address", "name": "manager_addr" },
    { "type": "address", "name": "reserve_addr" },
    { "type": "address", "name": "freeze_addr" },
    { "type": "address", "name": "clawback_addr" }
  ],
  "returns": { "type": "uint64" }
}

Calling asset_create creates a new Smart ASA and returns the identifier of the ASA. The metadata section describes its required properties.

Asset Configuration

[
  {
    "name": "asset_config",
    "args": [
      { "type": "asset", "name": "config_asset" },
      { "type": "uint64", "name": "total" },
      { "type": "uint32", "name": "decimals" },
      { "type": "bool", "name": "default_frozen" },
      { "type": "string", "name": "unit_name" },
      { "type": "string", "name": "name" },
      { "type": "string", "name": "url" },
      { "type": "byte[]", "name": "metadata_hash" },
      { "type": "address", "name": "manager_addr" },
      { "type": "address", "name": "reserve_addr" },
      { "type": "address", "name": "freeze_addr" },
      { "type": "address", "name": "clawback_addr" }
    ],
    "returns": { "type": "void" }
  },
  {
    "name": "get_asset_config",
    "readonly": true,
    "args": [{ "type": "asset", "name": "asset" }],
    "returns": {
      "type": "(uint64,uint32,bool,string,string,string,byte[],address,address,address,address)",
      "desc": "`total`, `decimals`, `default_frozen`, `unit_name`, `name`, `url`, `metadata_hash`, `manager_addr`, `reserve_addr`, `freeze_addr`, `clawback`"
    }
  }
]

Calling asset_config configures an existing Smart ASA.

Asset Transfer

{
  "name": "asset_transfer",
  "args": [
    { "type": "asset", "name": "xfer_asset" },
    { "type": "uint64", "name": "asset_amount" },
    { "type": "account", "name": "asset_sender" },
    { "type": "account", "name": "asset_receiver" }
  ],
  "returns": { "type": "void" }
}

Calling asset_transfer transfers a Smart ASA.

Asset Freeze

[
  {
    "name": "asset_freeze",
    "args": [
      { "type": "asset", "name": "freeze_asset" },
      { "type": "bool", "name": "asset_frozen" }
    ],
    "returns": { "type": "void" }
  },
  {
    "name": "account_freeze",
    "args": [
      { "type": "asset", "name": "freeze_asset" },
      { "type": "account", "name": "freeze_account" },
      { "type": "bool", "name": "asset_frozen" }
    ],
    "returns": { "type": "void" }
  }
]

Calling asset_freeze prevents any transfer of a Smart ASA. Calling account_freeze prevents a specific account from transferring or receiving a Smart ASA.

Asset Destroy

{
  "name": "asset_destroy",
  "args": [{ "type": "asset", "name": "destroy_asset" }],
  "returns": { "type": "void" }
}

Calling asset_destroy destroys a Smart ASA.

Circulating Supply

{
  "name": "get_circulating_supply",
  "readonly": true,
  "args": [{ "type": "asset", "name": "asset" }],
  "returns": { "type": "uint64" }
}

Calling get_circulating_supply returns the circulating supply of a Smart ASA.

Metadata

ASA Metadata

The ASA underlying a Smart ASA:

The metadata MUST be immutable.

Handling opt in and close out

A Smart ASA MUST require users to opt to the ASA and MAY require them to opt in to the controlling Smart Contract. This MAY be performed at two separate times.

Rationale

This ARC builds on the strengths of the ASA to enable a Smart Contract to control its operations and flexibly re-configure its configuration.

Copyright

Copyright and related rights waived via CCO.