映射
映射是一种键值数据结构,用于在智能合约中存储数据。在开罗,它们使用 LegacyMap
类型实现。值得注意的是,LegacyMap
类型只能在合约的 Storage
结构中使用,不能用在其他地方。
在此,我们演示如何在Cairo合约中使用 LegacyMap
类型,在 ContractAddress
类型的键和 felt252
类型的值之间进行映射。键值类型在角括号 <> 中指定。我们通过调用 write()
方法,传入键和值,写入映射。同样,我们可以通过调用 read()
方法并输入相关键值来读取与给定键值相关的值。
一些补充说明:
-
也有更复杂的键值对映射,例如,我们可以使用
LegacyMap::<(ContractAddress, ContractAddress), felt252>
在 ERC20 代币合约上创建一个代币授权许可。 -
在映射中,键
k_1,...,k_n
处的值的地址是h(...h(h(sn_keccak(variable_name),k_1),k_2),...,k_n)
,其中ℎ
是 Pedersen 哈希值,最终值取mod2251-256
。有关合约存储布局的更多信息,请参阅 Starknet Documentation。
use starknet::ContractAddress;
#[starknet::interface]
trait IMapContract<TContractState> {
fn set(ref self: TContractState, key: ContractAddress, value: felt252);
fn get(self: @TContractState, key: ContractAddress) -> felt252;
}
#[starknet::contract]
mod MapContract {
use starknet::ContractAddress;
#[storage]
struct Storage {
// The `LegacyMap` type is only available inside the `Storage` struct.
map: LegacyMap::<ContractAddress, felt252>,
}
#[abi(embed_v0)]
impl MapContractImpl of super::IMapContract<ContractState> {
fn set(ref self: ContractState, key: ContractAddress, value: felt252) {
self.map.write(key, value);
}
fn get(self: @ContractState, key: ContractAddress) -> felt252 {
self.map.read(key)
}
}
}