name: mvx_factory_manager description: 用于从模板部署和管理子合约的工厂模式。
MultiversX 工厂/管理器模式
三个核心操作:部署、跟踪、升级。
部署
#[endpoint(deployChild)]
fn deploy_child(&self, child_id: ManagedBuffer, init_arg: BigUint) -> ManagedAddress {
let template = self.template_address().get();
let metadata = CodeMetadata::UPGRADEABLE | CodeMetadata::READABLE | CodeMetadata::PAYABLE;
let new_address = self.tx()
.typed(child_proxy::ChildProxy)
.init(init_arg)
.from_source(template)
.code_metadata(metadata)
.returns(ReturnsNewManagedAddress)
.sync_call();
self.child_addresses().insert(new_address.clone());
self.child_by_id(&child_id).set(new_address.clone());
new_address
}
跟踪(注册表)
#[storage_mapper("templateAddress")]
fn template_address(&self) -> SingleValueMapper<ManagedAddress>;
#[storage_mapper("childAddresses")]
fn child_addresses(&self) -> SetMapper<ManagedAddress>;
#[storage_mapper("childById")]
fn child_by_id(&self, id: &ManagedBuffer) -> SingleValueMapper<ManagedAddress>;
#[storage_mapper("admins")]
fn admins(&self) -> UnorderedSetMapper<ManagedAddress>;
模式: SetMapper(迭代 + 包含)+ SingleValueMapper(ID查找)。
升级
#[endpoint(upgradeChild)]
fn upgrade_child(&self, child_id: ManagedBuffer) {
self.require_admin();
let child = self.child_by_id(&child_id).get();
require!(self.child_addresses().contains(&child), "未管理");
let metadata = CodeMetadata::UPGRADEABLE | CodeMetadata::READABLE | CodeMetadata::PAYABLE;
self.tx().to(child).typed(child_proxy::ChildProxy).upgrade()
.code_metadata(metadata)
.from_source(self.template_address().get())
.upgrade_async_call_and_exit();
}
CodeMetadata
| 标志 | 效果 |
|---|---|
UPGRADEABLE |
子合约可以升级(几乎总是需要) |
READABLE |
其他合约可以读取存储 |
PAYABLE |
可以直接接收EGLD |
反模式
- 部署而不跟踪(以后无法升级)
- 缺少
UPGRADEABLE标志 - 升级时未验证地址是受管理的子合约