如何在Ink! Substrate合约中实现类似Solidity的结构体映射功能
Ink! 合约实现结构体映射与赋值的方案
你当前编写的代码存在一处基础错误:#[ink(storage)] 是用于标记合约总存储入口结构体的属性,不能直接标注在业务数据结构体 BookEntry 上,你需要拆分业务数据结构、总存储结构再实现映射逻辑,完整实现代码如下:
#[ink::contract] mod btc_new { use ink_prelude::string::String; use ink_storage::Mapping; // 业务结构体:存储书籍信息,需实现序列化相关trait才能存入映射 #[derive(scale::Decode, scale::Encode, Clone, PartialEq, Debug, Default)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub struct BookEntry { book_id: String, book_name: String, author_name: String, is_released: bool, } // 合约总存储结构体:只有标记了#[ink(storage)]的结构体会被写入链上存储 #[ink(storage)] pub struct BtcNew { keyval: Mapping<String, BookEntry>, } impl BtcNew { /// 合约构造函数,部署时自动调用 #[ink(constructor)] pub fn new() -> Self { Self { keyval: Mapping::default() } } /// 对应Solidity的setBook方法,写入书籍信息 #[ink(message)] pub fn set_book(&mut self, book_id: String, book_name: String, author_name: String) -> String { let book_entry = BookEntry { book_id: book_id.clone(), book_name, author_name, is_released: true, }; self.keyval.insert(book_id.clone(), &book_entry); book_id } /// 可选补充:查询书籍信息的方法,用于验证写入结果 #[ink(message)] pub fn get_book(&self, book_id: String) -> Option<BookEntry> { self.keyval.get(book_id) } } }
关键逻辑说明
- 和Solidity的差异:Solidity的映射可直接声明在合约作用域,Ink!要求所有存储项都必须放在标注
#[ink(storage)]的总存储结构体中 - 业务结构体必须实现SCALE编码/解码相关的派生宏,才能正常写入链上存储
- Ink!映射的写入用
insert方法、读取用get方法,查询不存在的key时会返回None,可以根据需求自定义不存在场景的处理逻辑
内容的提问来源于stack exchange,提问作者Aditya Bharti
相关产品推荐
相关产品推荐

