Skip to main content

Module 0x2::dynamic_object_field

Similar to sui::dynamic_field, this module allows for the access of dynamic fields. But unlike, sui::dynamic_field the values bound to these dynamic fields must be objects themselves. This allows for the objects to still exist within in storage, which may be important for external tools. The difference is otherwise not observable from within Move.

use 0x1::option;
use 0x2::dynamic_field;
use 0x2::object;

Struct Wrapper

struct Wrapper<Name> has copy, drop, store
Fields
name: Name

Function add

Adds a dynamic object field to the object object: &mut UID at field specified by name: Name. Aborts with EFieldAlreadyExists if the object already has that field with that name.

public fun add<Name: copy, drop, store, Value: store, key>(object: &mut object::UID, name: Name, value: Value)
Implementation
public fun add<Name: copy + drop + store, Value: key + store>(
    // we use &mut UID in several spots for access control
    object: &mut UID,
    name: Name,
    value: Value,
) {
    let key = Wrapper { name };
    let id = object::id(&value);
    field::add(object, key, id);
    let (field, _) = field::field_info<Wrapper<Name>>(object, key);
    add_child_object(field.to_address(), value);
}

Function borrow

Immutably borrows the objects dynamic object field with the name specified by name: Name. Aborts with EFieldDoesNotExist if the object does not have a field with that name. Aborts with EFieldTypeMismatch if the field exists, but the value object does not have the specified type.

public fun borrow<Name: copy, drop, store, Value: store, key>(object: &object::UID, name: Name): &Value
Implementation
public fun borrow<Name: copy + drop + store, Value: key + store>(
    object: &UID,
    name: Name,
): &Value {
    let key = Wrapper { name };
    let (field, value_id) = field::field_info<Wrapper<Name>>(object, key);
    borrow_child_object<Value>(field, value_id)
}

Function borrow_mut

Mutably borrows the objects dynamic object field with the name specified by name: Name. Aborts with EFieldDoesNotExist if the object does not have a field with that name. Aborts with EFieldTypeMismatch if the field exists, but the value object does not have the specified type.

public fun borrow_mut<Name: copy, drop, store, Value: store, key>(object: &mut object::UID, name: Name): &mut Value
Implementation
public fun borrow_mut<Name: copy + drop + store, Value: key + store>(
    object: &mut UID,
    name: Name,
): &mut Value {
    let key = Wrapper { name };
    let (field, value_id) = field::field_info_mut<Wrapper<Name>>(object, key);
    borrow_child_object_mut<Value>(field, value_id)
}

Function remove

Removes the objects dynamic object field with the name specified by name: Name and returns the bound object. Aborts with EFieldDoesNotExist if the object does not have a field with that name. Aborts with EFieldTypeMismatch if the field exists, but the value object does not have the specified type.

public fun remove<Name: copy, drop, store, Value: store, key>(object: &mut object::UID, name: Name): Value
Implementation
public fun remove<Name: copy + drop + store, Value: key + store>(
    object: &mut UID,
    name: Name,
): Value {
    let key = Wrapper { name };
    let (field, value_id) = field::field_info<Wrapper<Name>>(object, key);
    let value = remove_child_object<Value>(field.to_address(), value_id);
    field::remove<Wrapper<Name>, ID>(object, key);
    value
}

Function exists_

Returns true if and only if the object has a dynamic object field with the name specified by name: Name.

public fun exists_<Name: copy, drop, store>(object: &object::UID, name: Name): bool
Implementation
public fun exists_<Name: copy + drop + store>(
    object: &UID,
    name: Name,
): bool {
    let key = Wrapper { name };
    field::exists_with_type<Wrapper<Name>, ID>(object, key)
}

Function exists_with_type

Returns true if and only if the object has a dynamic field with the name specified by name: Name with an assigned value of type Value.

public fun exists_with_type<Name: copy, drop, store, Value: store, key>(object: &object::UID, name: Name): bool
Implementation
public fun exists_with_type<Name: copy + drop + store, Value: key + store>(
    object: &UID,
    name: Name,
): bool {
    let key = Wrapper { name };
    if (!field::exists_with_type<Wrapper<Name>, ID>(object, key)) return false;
    let (field, value_id) = field::field_info<Wrapper<Name>>(object, key);
    field::has_child_object_with_ty<Value>(field.to_address(), value_id)
}

Function id

Returns the ID of the object associated with the dynamic object field Returns none otherwise

public fun id<Name: copy, drop, store>(object: &object::UID, name: Name): option::Option<object::ID>
Implementation
public fun id<Name: copy + drop + store>(
    object: &UID,
    name: Name,
): Option<ID> {
    let key = Wrapper { name };
    if (!field::exists_with_type<Wrapper<Name>, ID>(object, key)) return option::none();
    let (_field, value_addr) = field::field_info<Wrapper<Name>>(object, key);
    option::some(value_addr.to_id())
}