Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Tutorial Thumbnail
Beginner · 1 hour

Writing a Simple Smart Contract

Smart Contracts on the Algorand platform are very powerful and can be used to create many different applications. Writing a smart contract can be difficult and the tutorial is intended to help developers get started with a simple example. This tutorial walks through building an escrow style smart contract. The contract is then compiled and funded using the goal command-line tool and the Algorand dispenser. The tutorial also covers using and debugging the smart contract in a transaction on TestNet.

Requirements

Background

Before starting this tutorial, you should have access to an running node. See Installing a Node for more information. The node must be running on the TestNet network.

In this tutorial, we are writing a smart contract that functions like a funded escrow account. The first transaction that provides the following twelve-word passphrase will be able to spend from this account.

weather comfort erupt verb pet range endorse exhibit tree brush crane man

The tutorial will follow some of the suggested guidelines defined in the TEAL Guidelines.

Algorand supports using TEAL with contract accounts and delegating signature authority. These usage modes are described in Smart Contract Modes of Use. In this tutorial, we are using TEAL to create a contract account.

Warning

Anyone with the passphrase can spend from this account. The moment you send a transaction revealing the passphrase, anyone who sees that transaction may replace the recipient address with their own. Because of this, this contract should only be used on TestNet, in the context of this tutorial.

TEAL

Algorand uses the TEAL language for smart contract development which is an assembly-like language that runs on a stack machine. The primary function of a TEAL program is to approve or reject a transaction. More information about TEAL is available in the TEAL Overview.

Steps

1. Create the TEAL file

Using the editor of your choice, create a file named passphrase.teal. In this tutorial, this file is placed in the ~/node/teal directory.

2. Check the Transaction Fee

In the passphrase.teal file add the following code snippet.

// Check the Fee is resonable
// In this case 10,000 microalgos
txn Fee
int 10000
<=

The // symbols designate the line as a comment in TEAL. The txn Fee line loads the current transaction’s passed in fee amount onto the stack. The int 10000 line loads a constant value of 10000 onto the top of the stack. This results in two values on the stack. The <= returns either a 0 or 1 depending on whether the fee is smaller than 10000. This prevents a malicious transaction from clearing an account by setting the fee to an extremely large value.


Learn More
- TEAL Guidelines
- TEAL Opcodes

3. Check the Length of the Passed in Passphrase

In the passphrase.teal file add the following code snippet.

// Check the length of the passphrase is correct
arg 0
len
int 73
==
&&

In this code snippet, we first push the passphrase argument onto the top of the stack. Later in the tutorial, we will cover how to pass this value into a transaction. Notice that arg 0 represents the first argument to the TEAL program. The len opcode checks the length in bytes of the parameter. The int 73 line loads the integer value of 73 on to the top of the stack. The == command returns 1 if the length of the passphrase is 73 bytes, else a 0 is returned. The final && line just ANDs the previous condition from step 2 with this condition.

You can check the length of the passphrase by using the echo command from a terminal.

$ echo -n "weather comfort erupt verb pet range endorse exhibit tree brush crane man" | wc
       0      12      73

The byte length for our passphrase is 73 bytes.


Learn More
- TEAL Operations
- TEAL Opcodes

4. Check the SHA256 Value of the Passphrase

You can check the SHA256 value of the passed in the passphrase by using the following code snippet in the passphrase.teal file.

// The sha256 value of the passphrase
arg 0
sha256
byte base64 30AT2gOReDBdJmLBO/DgvjC6hIXgACecTpFDcP1bJHU=
==
&&

The arg 0 line pushes the passphrase argument onto the top of the stack. the sha256 opcode takes the value on the top of the stack and returns the SHA256 value. The byte base64 30AT2gOReDBdJmLBO/DgvjC6hIXgACecTpFDcP1bJHU= line loads a constant base64 encoded image on the top of the stack. The == line compares the SHA256 value of the passphrase to this image and returns 1 if they are equal, otherwise, it will return 0. The final && ANDs this condition with the previous conditions. You can get the byte image value for the TEAL program in various ways. To do get it using python from the command line use the following command.

$ python3 -c "import hashlib;import base64;print(base64.b64encode(hashlib.sha256(str('weather comfort erupt verb pet range endorse exhibit tree brush crane man').encode('utf-8')).digest()).decode('utf-8'))"
30AT2gOReDBdJmLBO/DgvjC6hIXgACecTpFDcP1bJHU=

Notice that the output of this command is what we are using for the image in the above code snippet.

5. Check the CloseRemainderTo value

The final condition of this example requires that the transaction’s receiver must also be equal to the CloseRemainderTo property of the transaction. This will close out the escrow and send the entire amount to the transaction receiver. This check can be done with the following code in the passphrase.teal file.

// Make sure the CloseRemainderTo is not set
txn CloseRemainderTo
txn Receiver 
==
&&

The txn CloseRemainderTo line pushes the CloseRemainderTo transaction property on to the top of the stack. The txn Receiver line pushes the Receiver value of the transaction on to the top of the stack. The == line compares these two values and returns 1 if they are equal and 0 if they are not equal. The final && ANDs this condition with all the previous conditions. The final file should now be saved.


Learn More
- Transaction Properties

6. Compile the TEAL

Using the command line from a terminal, compile the TEAL code using the following goal command.

$ goal clerk compile passphrase.teal
passphrase.teal: RZ2CUMV2VG3NCVFEVUVHVBYQUABQIBWAT3AC736Y6YL7PPDNAD7K3TVNAI

In the above example, goal is in the PATH. If you are in the ~/node/teal directory and goal is not in the path you can use ../goal clerk compile instead of goal clerk compile.

The compile step outputs an Algorand Address. In this example, the address is: RZ2CUMV2VG3NCVFEVUVHVBYQUABQIBWAT3AC736Y6YL7PPDNAD7K3TVNAI


Learn More
- GOAL TEAL example commands

7. Fund the Contract Account Using Dispenser

Using the Algorand TestNet Dispenser copy and paste the address from Step 6 into the dispenser and add Test tokens to the account.


Learn More
- TestNet Dispenser

8. Verify the Contract Account has been Funded

Using goal check the balance of the funded contract account using the following command:

$ goal account balance -a  RZ2CUMV2VG3NCVFEVUVHVBYQUABQIBWAT3AC736Y6YL7PPDNAD7K3TVNAI -d ~/node/data
100000000 microAlgos

9. Use a Non-Submitted Transaction to Debug the TEAL

Now that the smart contract is funded, you can test the Smart Contract logic. Before testing the smart contract, you will need to first run it and pass the passphrase as a base64 encoded string. When using goal all smart contract parameters must be base64 encoded and for contracts with multiple parameters, the order in which you pass these to goal directly maps to arg 0 arg 1 etc in TEAL. In this tutorial, our arg 0 is the passphrase below.

weather comfort erupt verb pet range endorse exhibit tree brush crane man

To base64 encode this parameter, use the following command.

$ echo -n "weather comfort erupt verb pet range endorse exhibit tree brush crane man" | base64
d2VhdGhlciBjb21mb3J0IGVydXB0IHZlcmIgcGV0IHJhbmdlIGVuZG9yc2UgZXhoaWJpdCB0cmVlIGJydXNoIGNyYW5lIG1hbg==

To pass this to a transaction you will need to use the --argb64 option in the goal command. We can also use the -o option to write the transaction to disk instead of submitting to the network.

goal clerk send -a 30000 --from-program passphrase.teal  -c STF6TH6PKINM4CDIQHNSC7QEA4DM5OJKKSACAPWGTG776NWSQOMAYVGOQE --argb64 d2VhdGhlciBjb21mb3J0IGVydXB0IHZlcmIgcGV0IHJhbmdlIGVuZG9yc2UgZXhoaWJpdCB0cmVlIGJydXNoIGNyYW5lIG1hbg==  -t STF6TH6PKINM4CDIQHNSC7QEA4DM5OJKKSACAPWGTG776NWSQOMAYVGOQE -o out.txn -d ~/node/data

This tutorial requires that the smart contract account get closed out and the receiver and the closeout account must be the same. This can be done using the -c and the -t options. Notice in the command above these values are equal.

With a contract account, the logic is only used when the contract is the sender of a transaction. We can specify that the transaction is from the smart contract using the --from-program option in the goal clerk send command.

The goal tool provides a method to print out how a transaction with the TEAL logic is processed. To use this feature, a transaction first must be written to file that is using the smart contract. This can be done by using the -o command option with goal clerk send. In this tutorial, the transaction is written to out.txn.

To see how the TEAL is processed run the following command.

$ goal clerk dryrun -t out.txn
tx[0] cost=25 trace:
  1 intcblock => <empty stack>
  6 bytecblock => <empty stack>
 41 txn => 1000 0x3e8
 43 intc_0 => 10000 0x2710
 44 <= => 1 0x1
 45 arg_0 => 7765617468657220636f6d666f72742065727570742076657262207065742072616e676520656e646f72736520657868696269742074726565206272757368206372616e65206d616e
 46 len => 73 0x49
 47 intc_1 => 73 0x49
 48 == => 1 0x1
 49 && => 1 0x1
 50 arg_0 => 7765617468657220636f6d666f72742065727570742076657262207065742072616e676520656e646f72736520657868696269742074726565206272757368206372616e65206d616e
 51 sha256 => df4013da039178305d2662c13bf0e0be30ba8485e000279c4e914370fd5b2475
 52 bytec_0 => df4013da039178305d2662c13bf0e0be30ba8485e000279c4e914370fd5b2475
 53 == => 1 0x1
 54 && => 1 0x1
 55 txn => 94cbe99fcf521ace086881db217e040706ceb92a5480203ec699bfff36d28398
 57 txn => 94cbe99fcf521ace086881db217e040706ceb92a5480203ec699bfff36d28398
 59 == => 1 0x1
 60 && => 1 0x1

 - pass -

The indication at the bottom of the output shows that the transaction will pass when sent to the network.


Learn More
- Parameter Passing with TEAL
- Debugging TEAL

10. Submit the Transaction to the Network

Submitting the transaction to the network can be done using goal clerk rawsend.

$ goal clerk rawsend -f out.txn -d ~/node/data
Raw transaction ID 7PKSBG2AWXNDQKFSRG73Z6TLN4IAFD2UFIPFWMLIANBEW7SEJ6MQ issued
Transaction 7PKSBG2AWXNDQKFSRG73Z6TLN4IAFD2UFIPFWMLIANBEW7SEJ6MQ still pending as of round 5138683
Transaction 7PKSBG2AWXNDQKFSRG73Z6TLN4IAFD2UFIPFWMLIANBEW7SEJ6MQ committed in round 5138685