Mappings provide persistent, on-chain key-value storage in Leo programs. They are similar to hash maps or dictionaries in other languages, but their state is stored on the Aleo blockchain and can be accessed by anyone.
final fn finalize_mint_public( public receiver: address, public amount: u64) { // Get existing balance, or use 0u64 if key doesn't exist let current_amount: u64 = Mapping::get_or_use(account, receiver, 0u64); Mapping::set(account, receiver, current_amount + amount);}
get_or_use() returns the existing value if the key exists, or the default value if the key doesn’t exist. This prevents errors when accessing non-existent keys.
program token.aleo { // On-chain storage of account balances mapping account: address => u64; // Public mint function fn mint_public(public receiver: address, public amount: u64) -> Final { return final { finalize_mint_public(receiver, amount); }; } // Public transfer function fn transfer_public( public receiver: address, public amount: u64 ) -> Final { return final { finalize_transfer_public(self.caller, receiver, amount); }; }}// Finalize functions that modify mappingsfinal fn finalize_mint_public( public receiver: address, public amount: u64) { let current_amount: u64 = Mapping::get_or_use(account, receiver, 0u64); Mapping::set(account, receiver, current_amount + amount);}final fn finalize_transfer_public( public sender: address, public receiver: address, public amount: u64) { // Deduct from sender let sender_amount: u64 = Mapping::get_or_use(account, sender, 0u64); Mapping::set(account, sender, sender_amount - amount); // Add to receiver let receiver_amount: u64 = Mapping::get_or_use(account, receiver, 0u64); Mapping::set(account, receiver, receiver_amount + amount);}
final fn update_if_greater( public key: address, public new_value: u64) { let current: u64 = Mapping::get_or_use(scores, key, 0u64); if new_value > current { Mapping::set(scores, key, new_value); }}
Mappings can only be modified from finalize functions within the program:
// Only finalize functions in this program can modify the mappingfinal fn finalize_update(public key: address, public value: u64) { Mapping::set(account, key, value);}
final fn safe_transfer( public sender: address, public receiver: address, public amount: u64) { let sender_balance: u64 = Mapping::get_or_use(account, sender, 0u64); // This will fail the transaction if sender_balance < amount let new_balance: u64 = sender_balance - amount; Mapping::set(account, sender, new_balance); let receiver_balance: u64 = Mapping::get_or_use(account, receiver, 0u64); Mapping::set(account, receiver, receiver_balance + amount);}
// On-chain storage of account balances.// Key: account address// Value: token balance in base unitsmapping account: address => u64;// Tracks the number of winners in the lottery.// Key: always 0u8 (single counter)// Value: current winner countmapping num_winners: u8 => u8;