Global Storage
Global state is associated with the app itself Global storage is a feature in Algorand that allows smart contracts to persistently store key-value pairs in a globally accessible state. This guide provides comprehensive information on how to allocate, read, write, and manipulate global storage within smart contracts.
Manipulating Global State Storage
Smart contracts can create, update, and delete values in global state using TEAL (Transaction Execution Approval Language) opcodes.
The number of values that can be written is limited by the initial configuration set during smart contract creation.
State is represented as key-value pairs, where keys are stored as byte slices (byte-array values), and values can be stored as either byte slices or uint64 values.
TEAL provides several opcodes for facilitating reading and writing to state, including app_global_put
, app_global_get
, app_global_get_ex
.
Allocation
Global storage can include between 0 and 64 key/value pairs and a total of 8K of memory to share among them. The amount of global storage is allocated in key/value units and determined at contract creation, which cannot be edited later. The contract creator address is responsible for funding the global storage by an increase to their minimum balance requirement.
1 def __init__(self) -> None:2 self.global_int_full = GlobalState(UInt64(50)) # UInt64 with default value = 503 self.global_int_simplified = UInt64(4 105 ) # UInt64 simplified with default value = 106 self.global_int_no_default = GlobalState(UInt64) # UInt64 with no default value7
8 # example: INIT_BYTES9 self.global_bytes_full = GlobalState(10 Bytes(b"Hello")11 ) # Bytes with default value = bytes(Hello)12 self.global_bytes_simplified = Bytes(13 b"Hello"14 ) # Bytes simplified with default value = bytes(Hello)15 self.global_bytes_no_default = GlobalState(Bytes) # Bytes with no default value16 # example: INIT_BYTES17
18 self.global_bool_simplified = True # Bool19 self.global_bool_no_default = GlobalState(bool) # Bool20
21 self.global_asset = GlobalState(Asset) # Asset22 self.global_application = GlobalState(Application) # Application23 self.global_account = GlobalState(Account) # Account
1#pragma version 102
3__init__:4 proto 0 05 byte "global_bytes_full"6 byte 0x48656c6c6f7 app_global_put8 byte "global_bytes_simplified"9 byte 0x48656c6c6f10 app_global_put11 retsub
Reading from Global State
The global storage of a smart contract can be read by any application call that specifies the contract’s application ID in its foreign apps array. The key-value pairs in global storage can be read on-chain directly, or off-chain using SDKs, APIs, and the goal CLI. Only the smart contract itself can write to its own global storage.
TEAL provides opcodes to read global state values for the current smart contract.
The app_global_get
opcode retrieve values from the current contract’s global storage, respectively.
The app_global_get_ex
opcode returns two values on the stack: a boolean
indicating whether the value was found, and the actual value
if it exists.
These _ex opcodes allow reading global 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.abimethod2 def get_global_state(self) -> UInt64:3 return self.global_int_full.get(default=UInt64(0))4
5 @arc4.abimethod6 def maybe_global_state(self) -> tuple[UInt64, bool]:7 int_value, int_exists = self.global_int_full.maybe() # uint648 if not int_exists:9 int_value = UInt64(0)10 return int_value, int_exists11
12 @arc4.abimethod13 def get_global_state_example(self) -> bool:14 assert self.global_int_full.get(default=UInt64(0)) == 50 # uint6415 assert self.global_int_simplified == UInt64(10) # get function cannot be used16 assert self.global_int_no_default.get(default=UInt64(0)) == 017
18 assert self.global_bytes_full.get(Bytes(b"default")) == b"Hello" # byte19 return True
1#pragma version 102
3get_global_state:4 proto 0 15 int 06 byte "global_int_full"7 app_global_get_ex8 int 09 cover 210 select11 retsub12
13maybe_global_state:14 proto 0 215 int 016 byte "global_int_full"17 app_global_get_ex18 dup19 uncover 220 swap21 bnz maybe_global_state_after_if_else@222 int 023 frame_bury 124
25maybe_global_state_after_if_else@2:26 frame_dig 127 frame_dig 028 uncover 329 uncover 330 retsub
Refer Sinppet Source to get global storage value for different data types
In addition to using TEAL, the global 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.
Example command:
goal app read --app-id 1 --guess-format --global --from <ADDRESS>
This command returns the global state of the smart contract with application ID 1, formatted for readability.
Example Output
1{2 "Creator": {3 "tb": "FRYCPGH25DHCYQGXEB54NJ6LHQG6I2TWMUV2P3UWUU7RWP7BQ2BMBBDPD4",4 "tt": 15 },6 "MyBytesKey": {7 "tb": "hello",8 "tt": 19 },10 "MyUintKey": {11 "tt": 2,12 "ui": 5013 }14}
Interpretation:
- The keys are
Creator
,MyBytesKey
, andMyUintKey
. - 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 thetb
field. The--guess-format
option automatically converts theCreator
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 theui
field.
The app_global_get_ex is used to read not only the global state of the current contract but any contract that is in the applications array. To access these foreign apps, they must be passed in with the application call.
goal app call --foreign-app APP1ID --foreign-app APP2ID
In addition to modifying its own global storage, a smart contract can read the global storage of any contract specified in its applications array. However, this is a read-only operation. The global state of other smart contracts cannot be modified directly. External smart contracts can be changed per smart contract call (transaction).
Writing to Global State
Can only be written by smart contract. To write to global state, use the app_global_put
opcode.
1 @arc4.abimethod2 def set_global_state(self, value: Bytes) -> None:3 self.global_bytes_full.value = value
1#pragma version 102
3set_global_state:4 proto 1 05 byte "global_bytes_full"6 frame_dig -17 app_global_put8 retsub
Refer Sinppet Source to set global storage value for different data types
Deleting Global State
Global storage is deleted when the corresponding smart contract is deleted. However, the smart contract can clear the contents of its global storage without affecting the minimum balance requirement.
1 @arc4.abimethod2 def del_global_state(self) -> bool:3 del self.global_int_full.value4 return True
1#pragma version 102
3del_global_state:4 proto 0 15 byte "global_int_full"6 app_global_del7 int 18 retsub
Refer Sinppet Source to delete global storage value for different data types
Summary of Global State Operations
For manipulating global storage data like reading, writing, deleting and checking if exists:
TEAL: Different opcodes can be used
Function | Description |
---|---|
app_global_get | Get global data for the current app |
app_global_get_ex | Get global data for other app |
app_global_put | Set global data to the current app |
app_global_del | Delete global data from the current app |
app_global_get_ex | Check if global data exists for the current app |
app_global_get_ex | Check if global data exists for the other app |
Different functions of globalState class can be used. The detailed api reference can be found here
Function | Description |
---|---|
GlobalState(type_) | Initialize a global state with the specified data type |
get(default) | Get data or a default value if not found |
maybe() | Get data and a boolean indicating if it exists |