Local Storage | Algorand 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.

public localInt = LocalState<uint64>({ key: 'int' })

public localIntNoDefault = LocalState<uint64>()

public localBytes = LocalState<bytes>()

public localString = LocalState<string>()

public localBool = LocalState<boolean>()

public localAccount = LocalState<Account>()
def __init__(self) -> None:
    ## Initialise local storages
    self.local_int = LocalState(UInt64)  # Uint64
    self.local_bytes = LocalState(Bytes)  # Bytes
    self.local_bool = LocalState(bool)  # Bool
    self.local_asset = LocalState(Asset)  # Asset
    self.local_application = LocalState(Application)  # Application
    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.

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.

/**
 * Updates multiple local state values for the transaction sender.
 * Requires the account to be opted into the application.
 * @param valueString - New string value to store
 * @param valueBool - New boolean value to store
 * @param valueAccount - New account address to store
 */
public writeLocalState(valueString: string, valueBool: boolean, valueAccount: Account): void {
  const sender = Txn.sender
  assert(sender.isOptedIn(Global.currentApplicationId), 'Account must opt in to contract first')
  this.localString(sender).value = valueString
  this.localBool(sender).value = valueBool
  this.localAccount(sender).value = valueAccount
  assert(this.localString(sender).value === valueString)
  assert(this.localBool(sender).value === valueBool)
  assert(this.localAccount(sender).value === valueAccount)
}

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.

/**
 * Clears all local state values for the transaction sender.
 * After calling this method, all local state values will be deleted.
 */
public clearLocalState(): void {
  const sender = Txn.sender
  assert(sender.isOptedIn(Global.currentApplicationId), 'Account must opt in to contract first')
  this.localInt(sender).delete()
  this.localIntNoDefault(sender).delete()
  this.localBytes(sender).delete()
  this.localString(sender).delete()
  this.localBool(sender).delete()
  this.localAccount(sender).delete()
}

Summary of Local State Operations

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

Function Description
app_local_get Get local data for the current app
app_local_get_ex Get local data for other app
app_local_put Set local data to the current app
app_local_del Delete local data from the current app

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

Function Description
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