Control Flow

PyTeal provides several control flow expressions to chain together multiple expressions and to conditionally evaluate expressions.

Exiting the Program: Return

The Return expression causes the program to exit immediately. It takes a single argument, which is the success value that the program should have. For example, Return(Int(0)) causes the program to immediately fail, and Return(Int(1)) causes the program to immediately succeed. Since the presence of a Return statement causes the program to exit, no operations after it will be executed.

Chaining Expressions: Seq

The Seq expression can be used to create a sequence of multiple expressions. It takes a single argument, which is a list of expressions to include in the sequence. For example:

Seq([
    App.globalPut(Bytes("creator"), Txn.sender()),
    Return(Int(1))
])

A Seq expression will take on the value of its last expression. Additionally, all expressions in a Seq expression, except the last one, must not return anything (e.g. evaluate to TealType.none). This restriction is in place because intermediate values must not add things to the TEAL stack. As a result, the following is an invalid sequence:

Invalid Seq expression
Seq([
    Txn.sender(),
    Return(Int(1))
])

If you must include an operation that returns a value in the earlier part of a sequence, you can wrap the value in a Pop expression to discard it. For example,

Seq([
    Pop(Txn.sender()),
    Return(Int(1))
])

Simple Branching: If

In an If expression,

If(test-expr, then-expr, else-expr)

the test-expr is always evaluated and needs to be typed TealType.uint64. If it results in a value greater than 0, then the then-expr is evaluated. Otherwise, else-expr is evaluated. Note that then-expr and else-expr must evaluate to the same type (e.g. both TealType.uint64).

You may also invoke an If expression without an else-expr:

If(test-expr, then-expr)

In this case, then-expr must be typed TealType.none.

There is also an alternate way to write an If expression that makes reading complex statements easier to read.

If(test-expr)
.Then(then-expr)
.ElseIf(test-expr)
.Then(then-expr)
.Else(else-expr)

Checking Conditions: Assert

The Assert expression can be used to ensure that conditions are met before continuing the program. The syntax for Assert is:

Assert(test-expr)

If test-expr is always evaluated and must be typed TealType.uint64. If test-expr results in a value greater than 0, the program continues. Otherwise, the program immediately exits and indicates that it encountered an error.

Example:

Assert(Txn.type_enum() == TxnType.Payment)

The above example will cause the program to immediately fail with an error if the transaction type is not a payment.

Chaining Tests: Cond

A Cond expression chians a series of tests to select a result expression. The syntax of Cond is:

Cond([test-expr-1, body-1],
     [test-expr-2, body-2],
     . . . )

Each test-expr is evaluated in order. If it produces 0, the paired body is ignored, and evaluation proceeds to the next test-expr. As soon as a test-expr produces a true value (> 0), its body is evaluated to produce the value for this Cond expression. If none of test-expr s evaluates to a true value, the Cond expression will be evaluated to err, a TEAL opcode that causes the runtime panic.

In a Cond expression, each test-expr needs to be typed TealType.uint64. A body could be typed either TealType.uint64 or TealType.bytes. However, all body s must have the same data type. Otherwise, a TealTypeError is triggered.

Example:

Cond([Global.group_size() == Int(5), bid],
     [Global.group_size() == Int(4), redeem],
     [Global.group_size() == Int(1), wrapup])

This PyTeal code branches on the size of the atomic transaction group.