Skip to main content

Module iota::dynamic_field

In addition to the fields declared in its type definition, an IOTA 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 copy, drop, and store abilities, e.g. an integer, a boolean, or a string. This gives IOTA programmers the flexibility to extend objects on-the-fly, and it also serves as a building block for core collection types

use iota::address; use iota::hex; use iota::object; use iota::tx_context; use std::ascii; use std::bcs; use std::option; use std::string; use std::vector;

Module Functions​

pub add​

Adds a dynamic 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>(object: &mut iota::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) }

pub borrow​

Immutably borrows the objects dynamic 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 does not have the specified type.

public fun borrow<Name: copy, drop, store, Value: store>(object: &iota::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 }

pub borrow_mut​

Mutably borrows the objects dynamic 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 does not have the specified type.

public fun borrow_mut<Name: copy, drop, store, Value: store>(object: &mut iota::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 }

pub exists_​

Returns true if and only if the object has a dynamic field with the name specified by name: Name but without specifying the Value type

public fun exists_<Name: copy, drop, store>(object: &iota::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) }

pub 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>(object: &iota::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) }

pub remove​

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

public fun remove<Name: copy, drop, store, Value: store>(object: &mut iota::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 }

pub 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 iota::object::UID, name: Name): std::option::Option<Value>

Implementation

public fun remove_if_exists<Name: copy + drop + store, Value: store>(     object: &mut UID,     name: Name, ): Option<Value> {     if (exists_<Name>(object, name)) {         option::some(remove(object, name))     } else {         option::none()     } }

pub(pkg) 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);

pub(pkg) borrow_child_object​

throws EFieldDoesNotExist if a child does not exist with that ID or throws EFieldTypeMismatch if the type does not match, and may also abort with EBCSSerializationFailure we need two versions to return a reference or a mutable reference

public(package) fun borrow_child_object<Child: key>(object: &iota::object::UID, id: address): &Child

Implementation

public(package) native fun borrow_child_object<Child: key>(object: &UID, id: address): &Child;

pub(pkg) borrow_child_object_mut​

public(package) fun borrow_child_object_mut<Child: key>(object: &mut iota::object::UID, id: address): &mut Child

Implementation

public(package) native fun borrow_child_object_mut<Child: key>(     object: &mut UID,     id: address, ): &mut Child;

pub(pkg) field_info​

public(package) fun field_info<Name: copy, drop, store>(object: &iota::object::UID, name: Name): (&iota::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()) }

pub(pkg) field_info_mut​

public(package) fun field_info_mut<Name: copy, drop, store>(object: &mut iota::object::UID, name: Name): (&mut iota::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()) }

pub(pkg) 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;

pub(pkg) 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;

pub(pkg) hash_type_and_key​

May abort with EBCSSerializationFailure.

public(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;

pub(pkg) remove_child_object​

throws EFieldDoesNotExist if a child does not exist with that ID or throws EFieldTypeMismatch if the type does not match, and may also abort with EBCSSerializationFailure.

public(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;

Structs​

struct Field​

Internal object used for storing the field and value

public struct Field<Name: copy, drop, store, Value: store> has key

Fields
id: iota::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​

err EFieldAlreadyExists​

The object already has a dynamic field with this name (with the value and type specified)

const EFieldAlreadyExists: u64 = 0;

err EFieldDoesNotExist​

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;

err EFieldTypeMismatch​

The object has a field with that name, but the value type does not match

const EFieldTypeMismatch: u64 = 2;

err EBCSSerializationFailure​

Failed to serialize the field's name

const EBCSSerializationFailure: u64 = 3;

err ESharedObjectOperationNotSupported​

The object added as a dynamic field was previously a shared object

const ESharedObjectOperationNotSupported: u64 = 4;