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 |