Asset Information

In addition to manipulating state on the blockchain, stateful smart contracts can also look up information about assets and account balances.

Algo Balances

The Balance expression can be used to look up an account’s balance in microAlgos (1 Algo = 1,000,000 microAlgos). For example,

senderBalance = Balance(Int(0)) # get the balance of Txn.accounts[0] (the sender)
account1Balance = Balance(Int(1)) # get the balance of Txn.accounts[1]

The MinBalance expression can be used to find an account’s minimum balance. This amount is also in microAlgos. For example,

senderMinBalance = MinBalance(Int(0)) # get the minimum balance of Txn.accounts[0] (the sender)
account1MinBalance = MinBalance(Int(1)) # get the minimum balance of Txn.accounts[1]

Additionally, Balance and MinBalance can be used together to calculate how many Algos an account can spend without closing. For example,

senderSpendableBalance = Balance(Int(0)) - MinBalance(Int(0)) # calculate how many Algos Txn.accounts[0] (the sender) can spend
account1SpendableBalance = Balance(Int(1)) - MinBalance(Int(1)) # calculate how many Algos Txn.accounts[1] can spend

Asset Holdings

In addition to Algos, the Algorand blockchain also supports additional on-chain assets called Algorand Standard Assets (ASAs). The AssetHolding group of expressions can be used to look up information about the ASAs that an account holds.

Similar to external state expressions, these expression return a MaybeValue. This value cannot be used directly, but has methods MaybeValue.hasValue() and MaybeValue.value().

If the account has opted into the asset being looked up, hasValue() will return 1 and value() will return the value being looked up (either the asset’s balance or frozen status). Otherwise, hasValue() and value() will return 0.

Balances

The AssetHolding.balance expression can be used to look up how many units of an asset an account holds. For example,

# get the balance of Txn.accounts[0] (the sender) for asset 31566704
# if the account is not opted into that asset, returns 0
senderAssetBalance = AssetHolding.balance(Int(0), Int(31566704))
program = Seq([
    senderAssetBalance,
    senderAssetBalance.value()
])

# get the balance of Txn.accounts[1] for asset 27165954
# if the account is not opted into that asset, exit with an error
account1AssetBalance = AssetHolding.balance(Int(1), Int(27165954))
program = Seq([
    account1AssetBalance,
    Assert(account1AssetBalance.hasValue()),
    account1AssetBalance.value()
])

Frozen

The AssetHolding.frozen expression can be used to check if an asset is frozen for an account. A value of 1 indicates frozen and 0 indicates not frozen. For example,

# get the frozen status of Txn.accounts[0] (the sender) for asset 31566704
# if the account is not opted into that asset, returns 0
senderAssetFrozen = AssetHolding.frozen(Int(0), Int(31566704))
program = Seq([
    senderAssetFrozen,
    senderAssetFrozen.value()
])

# get the frozen status of Txn.accounts[1] for asset 27165954
# if the account is not opted into that asset, exit with an error
account1AssetFrozen = AssetHolding.frozen(Int(1), Int(27165954))
program = Seq([
    account1AssetFrozen,
    Assert(account1AssetFrozen.hasValue()),
    account1AssetFrozen.value()
])

Asset Parameters

Every ASA has parameters that contain information about the asset and how it behaves. These parameters can be read by TEAL applications for any asset in the Txn.assets array.

The AssetParam group of expressions are used to access asset parameters. Like AssetHolding, these expressions return a MaybeValue.

The hasValue() method will return 0 only if the asset being looked up does not exist (i.e. the ID in Txn.assets does not represent an asset).

For optional parameters that are not set, hasValue() will still return 1 and value() will return a zero-length byte string (all optional parameters are TealType.bytes).

The different parameters that can be accessed are summarized by the table below. More information about each parameter can be found on the Algorand developer website.

Expression Type Description
AssetParam.total() TealType.uint64 The total number of units of the asset.
AssetParam.decimals() TealType.uint64 The number of decimals the asset should be formatted with.
AssetParam.defaultFrozen() TealType.uint64 Whether the asset is frozen by default.
AssetParam.unitName() TealType.bytes The name of the asset’s units.
AssetParam.name() TealType.bytes The name of the asset.
AssetParam.url() TealType.bytes A URL associated with the asset.
AssetParam.metadataHash() TealType.bytes A 32-byte hash associated with the asset.
AssetParam.manager() TealType.bytes The address of the asset’s manager account.
AssetParam.reserve() TealType.bytes The address of the asset’s reserve account.
AssetParam.freeze() TealType.bytes The address of the asset’s freeze account.
AssetParam.clawback() TealType.bytes The address of the asset’s clawback account.

Here’s an example that uses an asset parameter:

# get the total number of units for Txn.assets[0]
# if the asset is invalid, exit with an error
assetTotal = AssetParam.total(Int(0))
program = Seq([
    assetTotal,
    Assert(assetTotal.hasValue()),
    assetTotal.value()
])