映射

映射是一种键值数据结构,用于在智能合约中存储数据。在开罗,它们使用 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)
        }
    }
}

访问 Voyager 上的合约或在 Remix 中尝试它。

Last change: 2023-10-12, commit: 90aa7c0