Your First Application

Use the guide below to deploy a "hello world" Algorand application, a stateful smart contract using the Transaction Execution Approval Language (TEAL). This requires setting up your workspace and connecting to a node. This guide covers drafting the smart contract code, deploying to the network, interacting with and removing the application.

This is a very basic application which implements a counter. Each time the application is called, the counter value is incremented.


Algorand Smart Contracts (ASC1) are deployed as either "Stateful" or "Stateless" programs. Both use the Transaction Execution Approval Language (TEAL), but the available OpCodes and, therefore their function, vary by type. This guide covers only stateful smart contracts; learn more about stateless smart contracts.

Stateful Application Primer

The Overview of Algorand Stateful Smart Contracts should be consulted for details of the concepts covered in this document. Here is a brief primer to get started.

The term "stateful" means the application is able to store information or "maintain state" within the ledger. The information ("data") is structured into key/value pairs. The Transaction Execution Approval Language (TEAL) defines the available OpCodes for use during program execution. Application Call Transactions are used to interact with the application and may include arguments (additional data) that are evaluated by the program at run-time. Every program execution must complete with a single non-zero uint64 value (or use the return opcode with a non-zero uint64 on top of the stack) remaining on the stack to be valid and thus commit all state changes to the ledger.

Application Components


Every Algorand stateful application is comprised of at least two programs: approval and clear state.

Approval Program

The approval program is the main application logic for the smart contract.

Clear State Program

The clear state program is used to retire an application for specific users. This will clear the smart contract's local state variables from the user's balance record.

State Storage Locations

Applications have access to three storage locations for stateful data: global, local, and external.


Global data are stored within the application itself. The program will read from and write to its global storage the same regardless of which account submitted the application call transaction.


Each program may read from and write to local storage within the account object of the "calling account". This allows an application developer to store user-specific data and vary program execution logic at run-time per user.


Each program may read both the global and local state storage locations for a limited number of other external programs and accounts. For more information on external programs and accounts see the stateful smart contract documentation.

State Data

Both global and local data are stored as key/value pairs, where the key is bytes and the value may be either a bytes or uint64.

  "key": {
    "type": <1 || 2>,
    "value": <[]byte || uint64>

Program Execution

Application users will submit a call transaction to the application with appropriate arguments.

Application Call Transaction

Each application call transaction from a user account instructs the approval application to execute. Arguments may be specified within the call transaction and consumed by the program during execution.

State Access and Updates

TEAL provides OpCodes allowing the program to get (read) and put (write) data within state storage locations.


Programs may implicitly read their own global storage and the local storage of the account submitting the application call transaction.


Reading from global and local storage of an external program or account is allowed by explicitly passing the address as an argument within the application call transaction. Programs may read from global storage of external programs which are stored in the application array of an application call transaction. Additionally, programs may read from local storage of up to four (4) external accounts which are stored in the accounts array of an application call transaction. For more information on the applications and accounts arrays, see the stateful smart contract documentation.


Writing data is restricted to global storage of the "called" program and local storage of the "calling" account or any account in the accounts array, both specified within the application call transaction (note: external locations may only be read from). The local storage can only be modified if the account has opted into the application.

Draft Application Code

Approval Program

Create a new file named approval_program.teal and add the following code:

#pragma version 4

// read global state
byte "counter"

// increment the value
int 1

// store to scratch space
store 0

// update global state

// load return value as approval
load 0

!!! warning The above approval program is insecure and should not be used in a real application. In particular, anybody can update the approval program. For a real application, we recommend starting from the template provided in the Overview.

Define TEAL Version

The approval program instructs the Algorand Virtual Machine (AVM) to use "version 4" TEAL OpCodes during execution.

  • #pragma version 4
Read from Global State

This program has a single global key/value pair to store the number of times the program was called. The key is the string "counter" and the value will be defined as an integer when the application is created below.

  • byte "counter" places the bytes representing the string "counter" on the stack
  • dup duplicates that, so now "counter" is on the stack twice
  • app_global_get pops the top of the stack, looks within global for the key "counter" and places the value back on top of the stack.
Perform Program Logic

The program now has the current value for "counter" and will increment this value. A copy of this value will be stored in scratch space for use below. Note: scratch space is accessible by the program only during run-time and cannot persist any values after execution completes.

  • int 1 places the integer 1 on the stack
  • + pops two elements from the stack (the value for "counter" and int 1), sums them, and places the result back on top of the stack
  • dup duplicates the topmost value on the stack
  • store 0 pops the duplicate value from the stack and moves it to the first position within scratch space.
Write to Global State

Now the program will store the incremented value into global storage at key "counter". This value will persist on the ledger if the program completes successfully.

  • app_global_put pops two elements from the stack (key "counter" from line 5 and value calculated in line 11) and stores into global the value for key.

At this point the stack is empty. A valid approval program must complete with a single non-zero uint64 value remaining on the stack. If the value is 0x00 (false) the program will fail, all state transitions will be discarded, and the calling transaction will also fail. The scratch space still holds a duplicate copy of the counter value. Loading that ensures the program will complete successfully.

  • load 0 copies the first value from scratch space and places it on top of the stack
  • return use last value on stack as success value; end

Clear State Program

The clear state program is used by the application to clear the global and local state storage locations for the application and accounts. The "hello world" application does not evaluate any conditions and simply approves the call.

Create a new file named clear_state_program.teal and add the following code:

#pragma version 4
// This program clears program state

int 1

  • #pragma version 4 instructs the AVM to use "version 4" OpCodes during execution. This is required for stateful smart contract applications
  • int 1 places the integer 1 on the stack, signaling approval.

Deploy New Application

With the two program files completed, the application may be created on the blockchain using the bash script below. The script uses goal and requires a funded account $ADDR_CREATOR to pay the transaction fee. The flags are rather descriptive. Notice that only $GLOBAL_INTS has a value of 1 and is used to allocate a single global state storage element using the --global-ints flag.


export TEAL_APPROVAL_PROG="approval_program.teal"
export TEAL_CLEAR_PROG="clear_state_program.teal"

export GLOBAL_INTS=1
export LOCAL_INTS=0

goal app create --creator $ADDR_CREATOR \
                --approval-prog "$TEAL_APPROVAL_PROG" \
                --clear-prog "$TEAL_CLEAR_PROG" \
                --global-byteslices $GLOBAL_BYTESLICES \
                --global-ints $GLOBAL_INTS \
                --local-byteslices $LOCAL_BYTESLICES \
                --local-ints $LOCAL_INTS 


If you are using sandbox, you need to copy the approval and clear programs to sandbox beforehand. Concretely, after all the export commands, run:

./sandbox copy "$TEAL_APPROVAL_PROG"
./sandbox copy "$TEAL_CLEAR_PROG"
./sandbox goal app create ...
where ... should be replaced by the parameters above.


Attempting to create app (approval size 25, hash L4N6WP75R2G6M3TMLWSLA5S4PNHQIMGYTFMSOWNU6Q6X3R5LOU5A; clear size 5, hash YOE6C22GHCTKAN3HU4SE5PGIPN5UKXAJTXCQUPJ3KKF5HOAH646A)
Created app with app index 33

Application ID 33 was created above. Check yours using:

goal account dump --address $ADDR_CREATOR
  "algo": 308000,
  "appp": {
    "33": {
      "approv": "AiABASYBB2NvdW50ZXIoSWQiCEk1AGc0AA==",
      "clearp": "AiABASI=",
      "gs": {
        "counter": {
          "tt": 2,
          "ui": 1

Notice the "appp" section has "33" which is the application ID found within the creator's account. Export your specific value for use within future scripts using:

export APP_ID=<your_app_id>

Another way to view information about an application is with the following goal command:

goal app info --app-id $APP_ID


Application ID:        33
Max global byteslices: 0
Max global integers:   1
Max local byteslices:  0
Max local integers:    0

Notice the values for the Max state storage locations match those specified when the app was created above. These values may not be altered after creation.

Application Calls

There are a number of application calls available to interact with the application.

OptIn to Application

Most applications (if local state is used) require each user OptIn prior to interacting with the application. However, this "hello world" application did not allocate any local state when created so it will not require an OptIn application call by any accounts.

Read State

Both global and local state may be read by anyone accessing the ledger. The following displays the current state of your application:

goal app read --global --app-id $APP_ID
  "counter": {
    "tt": 2,
    "ui": 1
Here the single global key/value pair for your application is displayed. The key "counter" was assigned the type "tt" of integer at creation (1 for bytes, 2 for uint64). The current integer value "ui" is 1. The approval program executed once during creation.

Call Application

Calling the application again requires knowing the application id and paying the transaction fee. Anyone on the network may call this application, so modifying the --from flag will succeed if that account is funded.

goal app call --app-id $APP_ID --from $ADDR_CREATOR

Check the application state again:

goal app read --global --app-id $APP_ID
  "counter": {
    "tt": 2,
    "ui": 2
The "hello world" application has been called again as observed by the incremented value "ui" for key "counter". Continue making calls and reading the updated state.

Retire the Application

Each account is limited to creating or opting into a total of 10 applications. Removing an application may be accomplished using:

goal app delete --app-id $APP_ID --from $ADDR_CREATOR
Results for both goal account dump and goal app read will not include the application. You may reuse the existing program source files to create the application again. However, that will result in a new application id and a reset of your global "counter" state back to 1.