Public State
Mappings
There are several functions available to query and modify mappings. The examples below will reference the following mapping:
mapping balance: address => u64;
Querying
To simply check if a value has been set for a particular address in balance:
balance.contains(addr)
Mapping::contains(balance, addr); // Alternate syntax
To query a value for a particular address in balance:
balance.get(addr)
Mapping::get(balance, addr); // Alternate syntax
Note that if value at addr does not exist above, then the program will fail to execute. To query a value with a fallback for this case:
balance.get_or_use(addr,fallback_value)
Mapping::get_or_use(balance, addr, fallback_value); // Alternate syntax
A program can also query values from another program's mappings:
let balance1 = credits.aleo/account.get(addr);
let balance2 = credits.aleo/account.get_or_use(addr, 0u64);
Although values can be queried, a program cannot directly modify another program's mappings.
Modifying
To set a value for a particular address in balance:
balance.set(addr,value)
Mapping::set(balance, addr, value); // Alternate syntax
To remove the value set at particular address in balance:
balance.remove(addr)
Mapping::remove(balance, addr); // Alternate syntax
Usage
program map.aleo {
mapping balance: address => u64;
async transition dubble() -> Future {
return dubble_onchain(self.caller);
}
async function dubble_onchain(addr: address) {
let current_value: u64 = balance.get_or_use(addr, 0u64);
balance.set(addr, current_value + 1u64);
let next_current_value = balance.get(addr);
balance.set(addr, current_value + 1u64);
}
}
Mapping operations are only allowed in an async function or async block.
Storage Variables
Storage variables behave similar to option types. There are several functions available to query and modify singleton storage variables. The examples below will reference the following:
storage counter: u64;
Querying
To query the value currently stored at counter:
counter.unwrap();
Note that if counter has not been initialized, then the program will fail to execute. To query the value with a fallback for this case:
counter.unwrap_or(fallback_value);
Modifying
To set a value for counter:
counter = 5u64;
To unset the value at counter:
counter = none;
Usage
program storage_variable.aleo {
storage counter: u64;
async transition increment() -> Future {
return increment_onchain();
}
async function increment_onchain() {
let current_value: u64 = counter.unwrap_or(0u64);
counter = current_value + 1u64;
}
}
Storage variable operations are only allowed in an async function or async block.
External Access
Storage variables defined in another program can be accessed using the fully qualified form program_name.aleo/storage_name. External storage variables are read-only and cannot be modified.
For example, suppose another program defines the following storage variable:
program external_program.aleo {
storage counter: u64;
...
}
You may query this value from your program using:
let value: u64 = external_program.aleo/counter.unwrap();
As with local storage variables, calling unwrap() will cause execution to fail if the storage variable has not been initialized. To safely query the value with a fallback:
let value: u64 = external_program.aleo/counter.unwrap_or(0u64);
External storage variables cannot be assigned to or unset. The following operations are invalid:
external_program.aleo/counter = 5u64; // invalid
external_program.aleo/counter = none; // invalid
Storage Vectors
Storage vectors behave like dynamic arrays of values of a given type. Several functions are available to query and modify storage vectors. The examples below reference the following declaration:
storage id_numbers: [u64];
Querying
To query the element currently stored in id_numbers at index idx:
id_numbers.get(idx);
This returns u64?. If idx is out of bounds, the result is none.
To get the current length of id_numbers:
id_numbers.len();
This always returns a u32 and cannot fail.
Modifying
To set an element at index idx in id_numbers:
id_numbers.set(idx, value);
To push an element onto the end of id_numbers:
id_numbers.push(value);
To pop and return the last element of id_numbers:
id_numbers.pop();
To remove the element at index idx, return it, and replace it with the final element of id_numbers:
id_numbers.swap_remove(idx);
To clear every element in id_numbers:
id_numbers.clear();
clear()does not actually remove any values from the vector. It simply sets the length to0.- Similarly,
swap_remove()andpop()do not physically remove values. They reduce the length by1, ensuring the final element is no longer accessible.
Usage
program storage_vector.aleo {
storage id_numbers: [u64];
async transition add_id(new_id: u64) -> Future {
return add_id_onchain(new_id);
}
async function add_id_onchain(new_id: u64) {
id_numbers.push(new_id);
}
async transition remove_id(idx: u32) -> Future {
return remove_id_onchain(idx);
}
async function remove_id_onchain(idx: u32) {
id_numbers.swap_remove(idx);
}
}
Storage vector operations are only allowed in an async function or async block.
External Access
Storage vectors defined in another program can be accessed using the fully qualified form program_name.aleo/storage_name. External storage vectors are read-only and cannot be modified.
For example, suppose another program defines the following storage vector:
program external_program.aleo {
storage id_numbers: [u64];
}
You may query elements or the length of this vector from your program:
let first: u64? = external_program.aleo/id_numbers.get(0u32);
let length: u32 = external_program.aleo/id_numbers.len();
External storage vectors cannot be modified. The following operations are invalid:
external_program.aleo/id_numbers.push(5u64); // invalid
external_program.aleo/id_numbers.set(0u32, 5u64); // invalid
external_program.aleo/id_numbers.pop(); // invalid
external_program.aleo/id_numbers.swap_remove(0u32); // invalid
external_program.aleo/id_numbers.clear(); // invalid