无法通过工厂合约设置自定义合约元数据的问题排查
问题原因与解决方案
问题根源
当工厂合约通过reply调用自定义合约的UpdateRewardMetadata时,自定义合约再发起ArchwayMsg::UpdateContractMetadata,此时调用该元数据更新消息的地址是自定义合约自身,而非作为管理员的工厂合约。Archway的元数据校验逻辑要求发起UpdateContractMetadata的地址必须是目标合约(即自定义合约)的管理员,显然自定义合约自己不是自身管理员,因此触发了"metadata can only be created by the contract admin"错误。
修复方案
让工厂合约直接发起Archway的元数据更新消息,跳过自定义合约的中转环节。修改工厂合约的reply逻辑如下:
#[cfg_attr(not(feature = "library"), entry_point)] pub fn reply(deps: DepsMut<ArchwayQuery>, env: Env, msg: Reply) -> ArchwayResult<ContractError> { let config = CONFIG.load(deps.storage)?; if msg.id != INSTANTIATE_REPLY_ID { return Err(ContractError::InstantiateError {}); }; let reply = parse_reply_instantiate_data(msg); match reply { Ok(res) => { let msgs: Vec<CosmosMsg> = vec![ // 直接由工厂合约发起元数据更新 ArchwayMsg::UpdateContractMetadata { contract_address: res.contract_address, owner_address: Some(env.contract.address.to_string()), rewards_address: Some(env.contract.address.to_string()), } .into(), ]; Ok(Response::new().add_messages(msgs)) } Err(err) => Err(ContractError::Std(StdError::GenericErr { msg: err.to_string() })), } }
同时可以移除自定义合约中UpdateRewardMetadata相关的消息定义与实现,因为不再需要该中转逻辑。
补充说明
Archway合约元数据管理核心规则:
- 只有合约的管理员地址才能发起
UpdateContractMetadata消息 - 这里的"发起地址"指的是直接发送该CosmosMsg的地址,而非调用链上层的发起方
修改后,工厂合约作为自定义合约的管理员直接发起元数据更新,就能通过权限校验。
内容的提问来源于stack exchange,提问作者user22306396
相关产品推荐
相关产品推荐

