You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:45:03