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:
- The ABI interface for a controlling Smart Contract (the Smart Contract that controls a Smart ASA).
- The metadata required to denote a Smart ASA and define the association between an ASA and its controlling Smart Contract.
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:
- MUST be
DefaultFrozen. - MUST specify the ID of the controlling Smart Contract (see below); and
- MUST set the
ClawbackAddrto the account of such Smart Contract.
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.