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,但仍未解决问题。
问题根源
udict_set使用错误:TON的cell是不可变对象,调用dict~udict_set(...)不会修改原cell,必须接收方法返回的新cell才能保留字典的修改。- 字典加载逻辑缺失:仅用
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
相关产品推荐
相关产品推荐

