Module sui::dynamic_field
In addition to the fields declared in its type definition, a Sui object can have dynamic fields that can be added after the object has been constructed. Unlike ordinary field names (which are always statically declared identifiers) a dynamic field name can be any value with the
copydrop, and store abilities, e.g. an integer, a boolean, or a string.
This gives Sui programmers the flexibility to extend objects on-the-fly, and it also serves as a
building block for core collection types
- Struct Field
- Constants
- Function add
- Function borrow
- Function borrow_mut
- Function remove
- Function exists_
- Function remove_if_exists
- Function exists_with_type
- Function field_info
- Function field_info_mut
- Function hash_type_and_key
- Function add_child_object
- Function borrow_child_object
- Function borrow_child_object_mut
- Function remove_child_object
- Function has_child_object
- Function has_child_object_with_ty
use std::ascii;
use std::bcs;
use std::option;
use std::string;
use std::vector;
use sui::address;
use sui::hex;
use sui::object;
use sui::tx_context;
Struct Field
Internal object used for storing the field and value
public struct Field<Name: copy, drop, store, Value: store> has key
Fields
- 
id: sui::object::UID
- Determined by the hash of the object ID, the field name value and it's type, i.e. hash(parent.id || name || Name)
- 
name: Name
- The value for the name of this field
- 
value: Value
- The value bound to this field
Constants
The object already has a dynamic field with this name (with the value and type specified)
const EFieldAlreadyExists: u64 = 0;
Cannot load dynamic field. The object does not have a dynamic field with this name (with the value and type specified)
const EFieldDoesNotExist: u64 = 1;
The object has a field with that name, but the value type does not match
const EFieldTypeMismatch: u64 = 2;
Failed to serialize the field's name
const EBCSSerializationFailure: u64 = 3;
The object added as a dynamic field was previously a shared object
const ESharedObjectOperationNotSupported: u64 = 4;
Function add
Adds a dynamic field to the object
object: &mut UIDname: Name.
Aborts with EFieldAlreadyExistspublic fun add<Name: copy, drop, store, Value: store>(object: &mut sui::object::UID, name: Name, value: Value)
Implementation
public fun add<Name: copy + drop + store, Value: store>(
    // we use &mut UID in several spots for access control
    object: &mut UID,
    name: Name,
    value: Value,
) {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    assert!(!has_child_object(object_addr, hash), EFieldAlreadyExists);
    let field = Field {
        id: object::new_uid_from_hash(hash),
        name,
        value,
    };
    add_child_object(object_addr, field)
}
Function borrow
Immutably borrows the
objectname: Name.
Aborts with EFieldDoesNotExistEFieldTypeMismatchpublic fun borrow<Name: copy, drop, store, Value: store>(object: &sui::object::UID, name: Name): &Value
Implementation
public fun borrow<Name: copy + drop + store, Value: store>(object: &UID, name: Name): &Value {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    let field = borrow_child_object<Field<Name, Value>>(object, hash);
    &field.value
}
Function borrow_mut
Mutably borrows the
objectname: Name.
Aborts with EFieldDoesNotExistEFieldTypeMismatchpublic fun borrow_mut<Name: copy, drop, store, Value: store>(object: &mut sui::object::UID, name: Name): &mut Value
Implementation
public fun borrow_mut<Name: copy + drop + store, Value: store>(
    object: &mut UID,
    name: Name,
): &mut Value {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    let field = borrow_child_object_mut<Field<Name, Value>>(object, hash);
    &mut field.value
}
Function remove
Removes the
objectname: Name and returns the
bound value.
Aborts with EFieldDoesNotExistEFieldTypeMismatchpublic fun remove<Name: copy, drop, store, Value: store>(object: &mut sui::object::UID, name: Name): Value
Implementation
public fun remove<Name: copy + drop + store, Value: store>(object: &mut UID, name: Name): Value {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    let Field { id, name: _, value } = remove_child_object<Field<Name, Value>>(object_addr, hash);
    id.delete();
    value
}
Function exists_
Returns true if and only if the
objectname: Name but without specifying the Value type
public fun exists_<Name: copy, drop, store>(object: &sui::object::UID, name: Name): bool
Implementation
public fun exists_<Name: copy + drop + store>(object: &UID, name: Name): bool {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    has_child_object(object_addr, hash)
}
Function remove_if_exists
Removes the dynamic field if it exists. Returns the some(Value) if it exists or none otherwise.
public fun remove_if_exists<Name: copy, drop, store, Value: store>(object: &mut sui::object::UID, name: Name): std::option::Option<Value>
Function exists_with_type
Returns true if and only if the
objectname: Name with an assigned value of type Value.
public fun exists_with_type<Name: copy, drop, store, Value: store>(object: &sui::object::UID, name: Name): bool
Implementation
public fun exists_with_type<Name: copy + drop + store, Value: store>(
    object: &UID,
    name: Name,
): bool {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    has_child_object_with_ty<Field<Name, Value>>(object_addr, hash)
}
Function field_info
public(package) fun field_info<Name: copy, drop, store>(object: &sui::object::UID, name: Name): (&sui::object::UID, address)
Implementation
public(package) fun field_info<Name: copy + drop + store>(
    object: &UID,
    name: Name,
): (&UID, address) {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    let Field { id, name: _, value } = borrow_child_object<Field<Name, ID>>(object, hash);
    (id, value.to_address())
}
Function field_info_mut
public(package) fun field_info_mut<Name: copy, drop, store>(object: &mut sui::object::UID, name: Name): (&mut sui::object::UID, address)
Implementation
public(package) fun field_info_mut<Name: copy + drop + store>(
    object: &mut UID,
    name: Name,
): (&mut UID, address) {
    let object_addr = object.to_address();
    let hash = hash_type_and_key(object_addr, name);
    let Field { id, name: _, value } = borrow_child_object_mut<Field<Name, ID>>(object, hash);
    (id, value.to_address())
}
Function hash_type_and_key
May abort with
EBCSSerializationFailurepublic(package) fun hash_type_and_key<K: copy, drop, store>(parent: address, k: K): address
Implementation
public(package) native fun hash_type_and_key<K: copy + drop + store>(
    parent: address,
    k: K,
): address;
Function add_child_object
public(package) fun add_child_object<Child: key>(parent: address, child: Child)
Implementation
public(package) native fun add_child_object<Child: key>(parent: address, child: Child);
Function borrow_child_object
throws
EFieldDoesNotExistEFieldTypeMismatchEBCSSerializationFailurepublic(package) fun borrow_child_object<Child: key>(object: &sui::object::UID, id: address): &Child
Implementation
public(package) native fun borrow_child_object<Child: key>(object: &UID, id: address): &Child;
Function borrow_child_object_mut
public(package) fun borrow_child_object_mut<Child: key>(object: &mut sui::object::UID, id: address): &mut Child
Implementation
public(package) native fun borrow_child_object_mut<Child: key>(
    object: &mut UID,
    id: address,
): &mut Child;
Function remove_child_object
throws
EFieldDoesNotExistEFieldTypeMismatchEBCSSerializationFailurepublic(package) fun remove_child_object<Child: key>(parent: address, id: address): Child
Implementation
public(package) native fun remove_child_object<Child: key>(parent: address, id: address): Child;
Function has_child_object
public(package) fun has_child_object(parent: address, id: address): bool
Implementation
public(package) native fun has_child_object(parent: address, id: address): bool;
Function has_child_object_with_ty
public(package) fun has_child_object_with_ty<Child: key>(parent: address, id: address): bool
Implementation
public(package) native fun has_child_object_with_ty<Child: key>(parent: address, id: address): bool;