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

TON区块链中如何将HashMap作为独立存储项?加载遇Cell underflow错误

解决TON合约中HashMap存储导致的Cell Underflow错误

为了更好地序列化合约数据,我希望将HashMap作为独立项存储,当前尝试存储地址列表,编写了如下代码:

(int, slice, slice, cell) load_data() inline {
  var ds = get_data().begin_parse();

  return (
    ds~load_msg_addr(), ;; sender address
    ds~load_msg_addr(), ;; owner address
    ds~load_uint(32), ;; index value
    ds~load_ref() ;; dictionary
  );
}

() save_data(int index, slice sender_address, slice owner_address) impure inline {
  cell dict = new_dict();

  dict~udict_set(256, index, sender_address);

  set_data(
    begin_cell()
    .store_slice(sender_address)
    .store_slice(owner_address)
    .store_uint(index, 32)
    .store_ref(dict)
    .end_cell()
  );
}

尝试加载数据时触发错误:

Unable to execute get method. Got exit_code: 9

根据文档,该错误含义为:

9 - Compute Phase - Cell underflow. Read from slice primitive tried to read more bits or references than there are.

我尝试过使用store_dict替代store_ref等不同方式存储HashMap,但仍未解决问题。


问题根源

  1. udict_set使用错误:TON的cell是不可变对象,调用dict~udict_set(...)不会修改原cell,必须接收方法返回的新cell才能保留字典的修改。
  2. 字典加载逻辑缺失:仅用load_ref加载字典cell后,未将其转换为字典解析器,后续若要读取字典内容会因结构不匹配触发解析错误。

修正后的代码

修正的save_data函数

() save_data(int index, slice sender_address, slice owner_address) impure inline {
  cell dict = new_dict();
  // 接收udict_set返回的新cell,保留字典修改
  dict = dict~udict_set(256, index, sender_address);

  set_data(
    begin_cell()
    .store_slice(sender_address)
    .store_slice(owner_address)
    .store_uint(index, 32)
    .store_ref(dict)
    .end_cell()
  );
}

修正的load_data函数

(int, slice, slice, cell) load_data() inline {
  var ds = get_data().begin_parse();

  slice sender = ds~load_msg_addr();
  slice owner = ds~load_msg_addr();
  int idx = ds~load_uint(32);
  cell dict_cell = ds~load_ref();

  // 若需读取字典内容,需先转换为字典解析器
  // var dict = dict_cell~begin_parse().begin_dict(256);
  // 示例读取操作:slice stored_sender = dict~udict_get(idx);

  return (idx, sender, owner, dict_cell);
}

关键说明

  • TON中所有cell均为不可变对象,任何修改cell的方法都会返回新实例,必须接收返回值才能生效。
  • 加载字典cell后,需调用begin_dict(key_bits)将其转换为字典解析器,指定key的位数(此处为256位)后,才能执行udict_get等读取操作。

内容的提问来源于stack exchange,提问作者Nedko Dimitrov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:23:20