Algorand Smart Contract (ASC1)

Algorand Smart Contracts (ASC1s) are Layer 1 smart contracts that automatically enforce custom rules and logic, typically around how assets (ASAs or Algos) can be transferred. They are intended to provide a logic-driven way of approving transactions while providing insulation from an individual's private key. With ASC1s a user can delegate their signature authority to others or set up an escrow-style account where the logic determines when tokens or assets are removed from the escrow. A contract can be configured to allow compiling and signing the contract for others to submit on your behalf, or by compiling the contract to produce a new contract account (that anyone can fund) where the logic of the contract determines when and how the funds or assets are disseminated. 

Algorand Smart Contracts are implemented using a new language that is stack-based and created by Algorand, called Transaction Execution Approval Language (TEAL). This a non-Turing complete language that allows branch forwards but prevents recursive logic to maximize safety and performance. The TEAL logic functions in read-only mode where the current transactions or group of transaction variables can be examined but not modified. The logic also has access to constants, globals, and can make use of many operators to implement many common scenarios required in online transactions.

Because TEAL is essentially an assembly based language Algorand is also working on full SDK support and primary templates for common use cases that will help developers to get started. Stay tuned for more documentation on these new features coming soon.

Below you will find links to resources to get you started with Algorand Smart Contracts, including reference docs for TEAL, examples, and more.

Before jumping into the details, it should be noted that TEAL is a very powerful language. It can enable complex transactional scenarios, meshing together the trade of the native asset (the Algo), with the trade of Algorand Standard Assets, Atomic Transfers, and much more. With all of that power, it is imperative that developers fully understand the implications of specifying and sometimes, more importantly, NOT specifying various logic when creating or modifying TEAL scripts. Underneath the Resources section you will find a [non-exhaustive] list of general guidelines and tips and patterns when working with TEAL scripts that will help you avoid unintended consequences (like losing all your funds!).

Resources

TEAL Guidelines

  • Use or modify example templates which are designed to embody best practices.

  • TEAL code should validate as many txn fields as possible. Things not checked could become anything.

    • CloseRemainderTo or AssetCloseTo should be the intended recipient or equal to global ZeroAddress. An unchecked address could steal all the value!

    • When not closing out a contract account, Amount or AssetAmount should be checked to be equal to the intended transfer amount.

    • Fee should be less than some reasonable amount (in micro-Algos). An unchecked Fee could burn the entire value!

    • Type or TypeEnum can be checked to ensure something is a Payment or AssetXfer or other transaction type.

    • Sender doesn’t need to be checked. It gets checked automatically.

  • Using a contract account limits your exposure. (Mistakes and bugs can only lose as much as you put into that account. If you can close out that account it closes out any exposure.)

    • Counterpoint: using a regular private/public key account with delegated logic allows you to always use the private key to sign any transaction and not be locked in to only what the logic allows.

  • Contract accounts should have an expiration in the future (txn FirstValid > NNNN, or txn FirstValidTime > TTTT) after which the originator can reclaim their assets.

  • Delegated LogicSigs may wish to specify an expiration round in the future after which they will no longer function.

  • Transaction groups must be designed with ‘slots’ such that each transaction will know what position it is in. A transaction’s logic can check (txn GroupIndex == K && global GroupSize == M) and then also check specific other transactions by their index through gtxn N field

    • Example:

      • Txn[0] sends N Algos from A to B; program checks that (M/N >= desired exchange rate) and (gtxn 1 Receiver == A)

      • Txn[1] sends M AltCoin from B to A; program checks that (N/M >= desired exchange rate) and (gtxn 0 Receiver == B)

    • Corollary to checking as many txn fields as possible: be strict with other transactions that you care about.

TEAL Tips and Patterns

  • A contract account that requires CloseRemainderTo or AssetCloseTo being equal to the intended recipient is good for a conditional all-or-nothing payment.

  • A recurring payment contract should combine (FirstValid % N == 0) and (Lease == xxxxx), where N is the period of the recurring payment in rounds, at least 1000.

  • Some operations panic and exit the transaction validation with an immediate fail. For example a divide-by-zero. It’s possible to test for these and skip panicking instructions with a bnz branch-if-not-zero instruction.