Substrate pallet调用mutate更新StorageMap成员报EncodeLike未实现错误如何解决
错误原因
该报错和Messages结构体的编解码实现无关,完全是mutate方法的参数传递错误导致:
StorageMap的mutate方法第一个参数要求传入存储项对应的key(也就是你定义的Vec<u8>类型的键),但你代码里把取出来的Messages<T>类型的值val当作第一个参数传给了mutate,编译器尝试把Messages<T>当做键编码为Vec<u8>,自然就抛出了trait EncodeLike<Vec<u8>> is not implemented for Messages<T>的错误。
修复方案
你之前先get再匹配的逻辑属于冗余写法,mutate本身就会把对应key的存储值以可变引用的形式传给闭包,还能减少一次存储读取开销,修正后的完整代码如下:
#[pallet::weight(0)] pub fn update( origin: OriginFor<T>, key: Vec<u8>, header: Vec<u8>, ) -> DispatchResultWithPostInfo { let _origin_account = ensure_signed(origin)?; Payload::<T>::mutate(&key, |payload_opt| { match payload_opt { Some(val) => { println!("{:?}", val.header); // 结构体中header字段是Option类型,需要包一层Some val.header = Some(header); }, None => println!("Not found") } }); // 按函数返回值要求返回结果 Ok(().into()) }
额外注意事项
- 如果需要key不存在时自动创建新条目,可以在闭包的None分支赋值:
*payload_opt = Some(Messages { meta: None, header: Some(header) }) - 生产环境不要使用
println,链上逻辑建议用log库的宏输出日志,或者直接移除调试代码 - 不要随意使用
#[pallet::weight(0)],实际业务需要根据执行复杂度设置合理的weight,避免链上资源被滥用
内容的提问来源于stack exchange,提问作者Kalanamith
相关产品推荐
相关产品推荐

