State

Applications that need to maintain state can declare the state they need by passing an instance of a class where the State values have been defined as attributes.

See the developer docs for details.

See the Parameters Table for protocol level limits on State.

Warning

The static option on state values is enforced only when using the methods provided by the objects described here. It is still possible to overwrite or delete the values using the accessors provided by PyTeal or TEAL directly.

Warning

When using the GlobalStateBlob or LocalStateBlob, the keys used to store data are 1 byte in the range [0-255]. Care must be taken to prevent any other state values from overwriting those keys. For example if ReservedLocalStateValue tries to write to key 0x00 and a blob is already using that key, bad things will happen.

For documentation on box storage please see the Boxes page

State Declaration

State is declared by passing an instance of a class where the State values have been defined as attributes.

Declaration of state:

class DemoState:
    global_state_value = GlobalStateValue(TealType.uint64)
    local_state_value = LocalStateValue(TealType.bytes)

app = Application("StatefulApp", state=DemoState())

Usage in app logic:

# ...
# Set the value in the `global_state_value` we declared
app.state.global_state_value.set(Int(123))
# ...

Full Example

Global State

Global State holds the stateful values for the Application.

Global State Value

class beaker.state.GlobalStateValue[source]

Allows storage of state values for an application (global state)

stack_type

The type of the state value (either TealType.bytes or TealType.uint64)

key

key to use to store the the value, default is name of class variable

default

Default value for the state value

static

Boolean flag to denote that this state value can only be set once and not deleted.

descr

Description of the state value to provide some information to clients

delete() Expr[source]

deletes the key from state, if the value is static it will be a compile time error

exists() Expr[source]

checks if the value is set (to whatever value. Returns Int(1) if value is set, Int(0) otherwise.

get() Expr[source]

gets the value stored for this state value

get_else(val: Expr) Expr[source]

gets the value stored at the key. if none is stored, return the value passed

get_maybe() MaybeValue[source]

gets a MaybeValue that can be used for existence check

get_must() Expr[source]

gets the value stored at the key. if none is stored, Assert out of the program

set(val: Expr) Expr[source]

sets the value to the argument passed

Reserved Global State Value

class beaker.state.ReservedGlobalStateValue[source]

Reserved Application State (global state)

Used when there should be a number of reserved state fields but the keys are uncertain at build time.

stack_type

The type of the state value (either TealType.bytes or TealType.uint64)

Type

TealType

max_keys

Maximum number of keys to reserve for this reserved state value

Type

int

key_gen

A subroutine returning TealType.bytes, used to create a key where some data is stored.

Type

SubroutineFnWrapper

descr

Description of the state value to provide some information to clients

Type

str

__init__(stack_type: ~typing.Literal[<TealType.bytes: 1>, <TealType.uint64: 0>], max_keys: int, key_gen: pyteal.SubroutineFnWrapper | collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | None = None, descr: str | None = None, *, prefix: str | None = None)[source]

Global State Blob

class beaker.state.GlobalStateBlob[source]
__init__(keys: int | list[int] = 64, descr: str | None = None)[source]
read(start: Expr, stop: Expr) Expr[source]

Reads some bytes from the buffer

Parameters
  • start – An Expr that represents the start index to read from. Should evaluate to uint64.

  • stop – An Expr that represents the stop index to read until. Should evaluate to uint64.

Returns

The bytes read from the blob from start to stop

read_byte(idx: Expr) Expr[source]

Reads a single byte from the given index

Parameters

idx – An Expr that represents the index into the blob to read the byte from. Should evaluate to uint64.

Returns

A single byte as a uint64

write(start: Expr, buff: Expr) Expr[source]

Writes the buffer to the blob

Parameters
  • start – An Expr that represents where to start writing. Should evaluate to uint64.

  • buff – An Expr that represents the bytes to write. Should evaluate to bytes.

write_byte(idx: Expr, byte: Expr) Expr[source]

Writes a single byte to the given index

Parameters
  • idx – An Expr that represents the index to write the byte to. Should evaluate to uint64.

  • byte – An Expr That represents the index to write the byte to. Should evaluate to uint64.

Local State

If your application requires storage of state at the Account level, the state values can be declared in the same was as Global State above.

LocalStateValue

class beaker.state.LocalStateValue[source]

Allows storage of keyed values for an account opted into an application (local state)

stack_type

The type of the state value (either TealType.bytes or TealType.uint64)

key

key to use to store the the value, default is name of class variable

default

Default value for the state value

static

Boolean flag to denote that this state value can only be set once and not deleted.

descr

Description of the state value to provide some information to clients

__init__(stack_type: ~typing.Literal[<TealType.bytes: 1>, <TealType.uint64: 0>], key: pyteal.Expr | str | None = None, default: pyteal.Expr | None = None, static: bool = False, descr: str | None = None)[source]
delete() Expr[source]

deletes the key from state, if the value is static it will be a compile time error

exists() Expr[source]

checks if the value is set (to whatever value. Returns Int(1) if value is set, Int(0) otherwise.

get() Expr[source]

gets the value stored for this state value

get_else(val: Expr) Expr[source]

gets the value stored at the key. if none is stored, return the value passed

get_maybe() MaybeValue[source]

gets a MaybeValue that can be used for existence check

get_must() Expr[source]

gets the value stored at the key. if none is stored, Assert out of the program

set(val: Expr) Expr[source]

sets the value to the argument passed

ReservedLocalStateValue

class beaker.state.ReservedLocalStateValue[source]

Reserved Account State (local state)

Used when there should be a number of reserved state fields but the keys are uncertain at build time.

stack_type

The type of the state value (either TealType.bytes or TealType.uint64)

Type

TealType

max_keys

Maximum number of keys to reserve for this reserved state value

Type

int

key_gen

A subroutine returning TealType.bytes, used to create a key where some data is stored.

Type

SubroutineFnWrapper

descr

Description of the state value to provide some information to clients

Type

str

__init__(stack_type: ~typing.Literal[<TealType.bytes: 1>, <TealType.uint64: 0>], max_keys: int, key_gen: pyteal.SubroutineFnWrapper | collections.abc.Callable[[pyteal.Expr], pyteal.Expr] | None = None, descr: str | None = None, *, prefix: str | None = None)[source]

Local State Blob

class beaker.state.LocalStateBlob[source]
__init__(keys: int | list[int] = 16, descr: str | None = None)[source]
read(start: Expr, stop: Expr) Expr[source]

Reads some bytes from the buffer

Parameters
  • start – An Expr that represents the start index to read from. Should evaluate to uint64.

  • stop – An Expr that represents the stop index to read until. Should evaluate to uint64.

Returns

The bytes read from the blob from start to stop

read_byte(idx: Expr) Expr[source]

Reads a single byte from the given index

Parameters

idx – An Expr that represents the index into the blob to read the byte from. Should evaluate to uint64.

Returns

A single byte as a uint64

write(start: Expr, buff: Expr) Expr[source]

Writes the buffer to the blob

Parameters
  • start – An Expr that represents where to start writing. Should evaluate to uint64.

  • buff – An Expr that represents the bytes to write. Should evaluate to bytes.

write_byte(idx: Expr, byte: Expr) Expr[source]

Writes a single byte to the given index

Parameters
  • idx – An Expr that represents the index to write the byte to. Should evaluate to uint64.

  • byte – An Expr That represents the index to write the byte to. Should evaluate to uint64.

Full Example

import pyteal as pt

import beaker


class ExampleState:
    declared_global_value = beaker.GlobalStateValue(
        stack_type=pt.TealType.bytes,
        default=pt.Bytes(
            "A declared state value that is protected with the `static` flag"
        ),
        descr="A static declared variable, nothing at the protocol level protects it, "
        "only the methods defined on ApplicationState do",
        static=True,
    )

    reserved_global_value = beaker.ReservedGlobalStateValue(
        stack_type=pt.TealType.uint64,
        max_keys=32,
        descr="A reserved app state variable, with 32 possible keys",
    )

    global_blob = beaker.GlobalStateBlob(
        keys=16,
    )

    declared_local_value = beaker.LocalStateValue(
        stack_type=pt.TealType.uint64,
        default=pt.Int(1),
        descr="An int stored for each account that opts in",
    )

    reserved_local_value = beaker.ReservedLocalStateValue(
        stack_type=pt.TealType.bytes,
        max_keys=8,
        descr="A reserved state value, allowing 8 keys to be reserved, "
        "in this case byte type",
    )

    local_blob = beaker.LocalStateBlob(keys=3)


app = (
    beaker.Application("StateExample", state=ExampleState())
    .apply(beaker.unconditional_create_approval, initialize_global_state=True)
    .apply(beaker.unconditional_opt_in_approval, initialize_local_state=True)
)


@app.external
def write_local_blob(v: pt.abi.String) -> pt.Expr:
    return app.state.local_blob.write(pt.Int(0), v.get())


@app.external
def read_local_blob(*, output: pt.abi.DynamicBytes) -> pt.Expr:
    return output.set(
        app.state.local_blob.read(
            pt.Int(0), app.state.local_blob.blob.max_bytes - pt.Int(1)
        )
    )


@app.external
def write_global_blob(v: pt.abi.String) -> pt.Expr:
    return app.state.global_blob.write(pt.Int(0), v.get())


@app.external
def read_global_blob(*, output: pt.abi.DynamicBytes) -> pt.Expr:
    return output.set(
        app.state.global_blob.read(
            pt.Int(0), app.state.global_blob.blob.max_bytes - pt.Int(1)
        )
    )


@app.external
def set_global_state_val(v: pt.abi.String) -> pt.Expr:
    # This will fail, since it was declared as `static` and initialized to
    # a default value during create
    return app.state.declared_global_value.set(v.get())


@app.external(read_only=True)
def get_global_state_val(*, output: pt.abi.String) -> pt.Expr:
    return output.set(app.state.declared_global_value)


@app.external
def set_reserved_global_state_val(k: pt.abi.Uint8, v: pt.abi.Uint64) -> pt.Expr:
    # Accessing the key with square brackets, accepts both Expr and an ABI type
    # If the value is an Expr it must evaluate to `TealType.bytes`
    # If the value is an ABI type, the `encode` method is used to convert it to bytes
    return app.state.reserved_global_value[k].set(v.get())


@app.external(read_only=True)
def get_reserved_global_state_val(k: pt.abi.Uint8, *, output: pt.abi.Uint64) -> pt.Expr:
    return output.set(app.state.reserved_global_value[k])


@app.external
def set_local_state_val(v: pt.abi.Uint64) -> pt.Expr:
    # Accessing with `[Txn.sender()]` is redundant but
    # more clear what is happening
    return app.state.declared_local_value[pt.Txn.sender()].set(v.get())


@app.external
def incr_local_state_val(v: pt.abi.Uint64) -> pt.Expr:
    # Omitting [Txn.sender()] just for demo purposes
    return app.state.declared_local_value.increment(v.get())


@app.external(read_only=True)
def get_local_state_val(*, output: pt.abi.Uint64) -> pt.Expr:
    return output.set(app.state.declared_local_value[pt.Txn.sender()])


@app.external
def set_reserved_local_state_val(k: pt.abi.Uint8, v: pt.abi.String) -> pt.Expr:
    return app.state.reserved_local_value[k][pt.Txn.sender()].set(v.get())


@app.external(read_only=True)
def get_reserved_local_state_val(k: pt.abi.Uint8, *, output: pt.abi.String) -> pt.Expr:
    return output.set(app.state.reserved_local_value[k][pt.Txn.sender()])