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)  # Account1#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    retsubReading 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 True1#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    retsubRefer 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 ttfield 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 thetbfield. The--guess-formatoption automatically converts theCreatorvalue to an Algorand address with a checksum (instead of displaying the raw 32-byte public key).
- When tt=2, the value is stored in theuifield.
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 APP2IDIn 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 = value1#pragma version 102
3set_global_state:4    proto 1 05    byte "global_bytes_full"6    frame_dig -17    app_global_put8    retsubRefer 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 True1#pragma version 102
3del_global_state:4    proto 0 15    byte "global_int_full"6    app_global_del7    int 18    retsubRefer 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 |