Skip to content
This new developer portal is under construction. For complete documentation, please refer to the old developer portal.

Local Storage

Local state is associated with each account that opts into the application. Algorand smart contracts offer local storage, which enables accounts to maintain persistent key-value data. This data is accessible to authorized contracts and can be queried from external sources.

Manipulating Local State

Smart contracts can create, update, and delete values in local state. The number of values that can be written is limited by the initial configuration set during smart contract creation.

TEAL (Transaction Execution Approval Language) provides several opcodes for facilitating reading and writing to state including app_local_put, app_local_get and app_local_get_ex. In addition to using TEAL, the local state values of a smart contract can be read externally using SDKs and the goal CLI. These reads are non-transactional queries that retrieve the current state of the contract.

Allocation

Local storage is allocated when an account opts into a smart contract by submitting an opt-in transaction. Each account can have between 0 and 16 key-value pairs in local storage, with a total of 2KB memory shared among them. The amount of local storage is determined during smart contract creation and cannot be edited later. The opted-in user account is responsible for funding the local storage by increasing their minimum balance requirement.

1
def __init__(self) -> None:
2
## Initialise local storages
3
self.local_int = LocalState(UInt64) # Uint64
4
self.local_bytes = LocalState(Bytes) # Bytes
5
self.local_bool = LocalState(bool) # Bool
6
self.local_asset = LocalState(Asset) # Asset
7
self.local_application = LocalState(Application) # Application
8
self.local_account = LocalState(Account) # Account

Reading from Local State

Local storage values are stored in the account’s balance record. Any account that sends a transaction to the smart contract can have its local storage modified by the smart contract, as long as the account has opted into the smart contract. Local storage can be read by any application call that has the smart contract’s app ID in its foreign apps array and the account in its foreign accounts array. In addition to the transaction sender, a smart contract call can reference up to four additional accounts whose local storage can be manipulated for the current smart contract, as long as those accounts have opted into the contract.

These five accounts can have their storage values read for any smart contract on Algorand by specifying the application ID of the smart contract, if the additional contract is included in the transaction’s applications array. This is a read-only operation and does not allow one smart contract to modify the local state of another. The additionally referenced accounts can be changed per smart contract call (transaction). The key-value pairs in local storage can be read on-chain directly or off-chain using SDKs and the goal CLI. Local storage is editable only by the smart contract itself, but it can be deleted by either the smart contract or the user account (using a ClearState call).

TEAL provides opcodes to read local state values for the current smart contract. The app_local_get opcode retrieves values from the current contract’s local storage. The app_local_get_ex opcode returns two values on the stack: a boolean indicating whether the value was found, and the actual value if it exists.

The _ex opcodes allow reading local states from other accounts and smart contracts, as long as the account and contract are included in the accounts and applications arrays. Branching logic is typically used after calling the _ex opcodes to handle cases where the value is found or not found.

1
@arc4.abimethod
2
def get_item_local_data(self, for_account: Account) -> UInt64:
3
return self.local_int[for_account]
4
5
# get function
6
@arc4.abimethod
7
def get_local_data_with_default_int(self, for_account: Account) -> UInt64:
8
return self.local_int.get(for_account, default=UInt64(0)) # Uint64
9
10
# maybe function
11
@arc4.abimethod
12
def maybe_local_data(self, for_account: Account) -> tuple[UInt64, bool]:
13
# used to get data or assert int
14
result, exists = self.local_int.maybe(for_account) # Uint64
15
if not exists:
16
result = UInt64(0)
17
return result, exists

Refer Sinppet Source to get local storage value for different data types

The local state values of a smart contract can also be read externally using cli. The below command reads are non-transactional queries that retrieve the current state of the contract.

Example command:

Terminal window
goal app read --app-id 1 --guess-format --local --from <ADDRESS>

This command will return the local state for the account specified by --from.

Example output with 3 key-value pairs

Output.json
1
{
2
"Creator": {
3
"tb": "FRYCPGH25DHCYQGXEB54NJ6LHQG6I2TWMUV2P3UWUU7RWP7BQ2BMBBDPD4",
4
"tt": 1
5
},
6
"MyBytesKey": {
7
"tb": "hello",
8
"tt": 1
9
},
10
"MyUintKey": {
11
"tt": 2,
12
"ui": 50
13
}
14
}

Interpretation:

  • The keys are Creator, MyBytesKey, and MyUintKey.
  • The tt field indicates the type of the value: 1 for byte slices (byte-array values), 2 for uint64 values.
  • When tt=1, the value is stored in the tb field. The --guess-format option automatically converts the Creator value to an Algorand address with a checksum (instead of displaying the raw 32-byte public key).
  • When tt=2, the value is stored in the ui field.

Writing to Local State

To write to local state, use the app_local_put opcode. An additional account parameter is provided to specify which account’s local storage should be modified.

1
@arc4.abimethod
2
def set_local_int(self, for_account: Account, value: UInt64) -> None:
3
self.local_int[for_account] = value # Uint64

Refer Sinppet Source to set local storage value for different data types

Deletion of Local State

Deleting a smart contract does not affect its local storage. Accounts must clear out of the smart contract to recover their minimum balance. Every smart contract has an ApprovalProgram and a ClearStateProgram. An account holder can clear their local state for a contract at any time by executing a ClearState transaction, deleting their data and freeing up their locked minimum balance. An account can request to clear its local state using a closeout transaction or clear its local state for a specific contract using a clearstate transaction, which will always succeed, even after the contract is deleted.

1
@arc4.abimethod
2
def delete_local_data(self, for_account: Account) -> None:
3
del self.local_account[for_account] # Uint64

Refer Sinppet Source to delete local storage value for different data types

Summary of Local State Operations

For manipulating local storage data like reading, writing, deleting and checking if exists:

TEAL: Different opcodes can be used

FunctionDescription
app_local_getGet local data for the current app
app_local_get_exGet local data for other app
app_local_putSet local data to the current app
app_local_delDelete local data from the current app
app_local_get_exCheck if local data exists for the current app
app_local_get_exCheck if local data exists for the other app

Different functions of LocalState class can be used. The detailed api reference can be found here

FunctionDescription
LocalState(type_)Initialize a local state with the specified data type
getitem(account)Get data for the given account
get(account, default)Get data for the given account, or a default value if not found
maybe(account)Get data for the given account, and a boolean indicating if it exists
setitem(account, value)Set data for the given account
delitem(account)Delete data for the given account
contains(account)Check if data exists for the given account