使用动态字段管理合约状态

动态字段的另一个有用应用是管理合约状态。你可能会倾向于为每个状态结构体使用多个共享对象。 例如,我们可以为笔记本电脑商店的配置设置如下:

public struct PriceConfigs has key {
    id: UID,
    price_range: vector<u64>,
}

public struct StoreHours has key {
    id: UID,
    open_hours: vector<vector<u8>>,
}

public struct SpecConfigs has key {
    id: UID,
    specs_range: vector<u64>,
}

fun init(ctx: &mut TxContext) {
    let price_configs = PriceConfigs {
        id: object::new(ctx),
        price_range: vector[1000, 5000],
    };
    let store_hours = StoreHours {
        id: object::new(ctx),
        open_hours: vector[vector[9, 12], vector[1, 5]],
    };
    let spec_configs = SpecConfigs {
        id: object::new(ctx),
        specs_range: vector[1000, 10000],
    };
    transfer::share_object(price_configs);
    transfer::share_object(store_hours);
    transfer::share_object(spec_configs);
}

创建共享对象并不是一项繁重的工作。每个对象都是共享的,因此用户在购买笔记本电脑时可以访问和/或修改这些对象。例如:

public fun purchase_laptop(price_configs: &PriceConfigs, store_hours: &SotreHours, 
spec_configs: &SpecConfigs, laptop: String, price: u64, ctx: &mut TxContext) {
}

如你所见,这个函数的签名太长且难以阅读。此外,代表用户提交交易的 Web 界面需要跟踪所有这些共享对象的地址。想象一下, 如果我们有 5 个甚至 10 个共享对象会发生什么!这也显得过于复杂,因为这些不同的结构体从未分离并独立存在,因此它们实际上并不需要成为对象。

更简洁的方法是创建一个单一的状态配置对象,并在那里添加动态字段:

public struct StateConfigs has key {
    id: UID,
}

const PRICE_CONFIGS: vector<u8> = b"PRICE_CONFIGS";

public struct PriceConfigs has store {
    price_range: vector<u64>,
}

const STORE_HOURS: vector<u8> = b"STORE_HOURS";

public struct StoreHours has store {
    open_hours: vector<vector<u8>>,
}

const SPEC_CONFIGS: vector<u8> = b"SPEC_CONFIGS";

public struct SpecConfigs has store {
    specs_range: vector<u64>,
}

fun init(ctx: &mut TxContext) {
    let state_configs = StateConfigs {
        id: object::new(ctx),
    };
    
    dynamic_fields::add(&mut state_configs.id, PRICE_CONFIGS, PriceConfigs {
        id: object::new(ctx),
        price_range: vector[1000, 5000],
    });
    
    dynamic_fields::add(&mut state_configs.id, STORE_HOURS, StoreHours {
        id: object::new(ctx),
        open_hours: vector[vector[9, 12], vector[1, 5]],
    });
    
    dynamic_fields::add(&mut state_configs.id, SPEC_CONFIGS, SpecConfigs {
        id: object::new(ctx),
        specs_range: vector[1000, 10000],
    });
    
    transfer::share(state_configs);
}

用户交易只需要跟踪并传递一个对象的地址:

public fun purchase_laptop(state_configs: &StateConfigs, laptop: String, price: u64, ctx: &mut TxContext) {
}

正如你所见,这样简洁得多!