State Management | Algorand Developer Portal

State Management

algorand-python-testing provides tools to test state-related abstractions in Algorand smart contracts. This guide covers global state, local state, boxes, and scratch space management.

import algopy

from algopy_testing import algopy_testing_context

# Create the context manager for snippets below

ctx_manager = algopy_testing_context()

# Enter the context

context = ctx_manager.__enter__()

Global State

Global state is represented as instance attributes on algopy.Contract and algopy.ARC4Contract classes.

class MyContract(algopy.ARC4Contract):

def __init__(self):

self.state_a = algopy.GlobalState(algopy.UInt64, key="global_uint64")

self.state_b = algopy.UInt64(1)

# In your test

contract = MyContract()

contract.state_a.value = algopy.UInt64(10)

contract.state_b.value = algopy.UInt64(20)

Local State

Local state is defined similarly to global state, but accessed using account addresses as keys.

class MyContract(algopy.ARC4Contract):

def __init__(self):

self.local_state_a = algopy.LocalState(algopy.UInt64, key="state_a")

# In your test

contract = MyContract()

account = context.any.account()

contract.local_state_a[account] = algopy.UInt64(10)

Boxes

The framework supports various Box abstractions available in algorand-python.

class MyContract(algopy.ARC4Contract):

def __init__(self):

self.box_map = algopy.BoxMap(algopy.Bytes, algopy.UInt64)

@algopy.arc4.abimethod()

def some_method(self, key_a: algopy.Bytes, key_b: algopy.Bytes, key_c: algopy.Bytes) -> None:

self.box = algopy.Box(algopy.UInt64, key=key_a)

self.box.value = algopy.UInt64(1)

self.box_map[key_b] = algopy.UInt64(1)

self.box_map[key_c] = algopy.UInt64(2)

# In your test

contract = MyContract()

key_a = b"key_a"

key_b = b"key_b"

key_c = b"key_c"

contract.some_method(algopy.Bytes(key_a), algopy.Bytes(key_b), algopy.Bytes(key_c))

# Access boxes

box_content = context.ledger.get_box(contract, key_a)

assert context.ledger.box_exists(contract, key_a)

# Set box content manually

with context.txn.create_group():

context.ledger.set_box(contract, key_a, algopy.op.itob(algopy.UInt64(1)))

Scratch Space

Scratch space is represented as a list of 256 slots for each transaction.

class MyContract(algopy.Contract, scratch_slots=(1, 2, algopy.urange(3, 20))):

def approval_program(self):

algopy.op.Scratch.store(1, algopy.UInt64(5))

assert algopy.op.Scratch.load_uint64(1) == algopy.UInt64(5)

return True

# In your test

contract = MyContract()

result = contract.approval_program()

assert result

scratch_space = context.txn.last_group.get_scratch_space()

assert scratch_space[1] == algopy.UInt64(5)

For more detailed information, explore the example contracts in the examples/ directory, the coverage page, and the API documentation.

ctx_manager.__exit__(None, None, None)