Can we load an object by ID during a move call?

Originally asked on Discord.

The short answer to this is “no” – address-owned, shared and immutable objects all need to be specified as inputs to entry functions, so it is not possible to load them dynamically by ID in the middle of a move call transaction.

However, Dynamic Fields can be loaded dynamically, so if you find yourself needing to load an object by its ID during a move call, a useful pattern is to add those objects as dynamic fields to an over-arching parent, which is passed in as entry function for access. The Bag collection type is an example of this pattern:

module example::dynamic_loading {
    use std::string::{Self, String};
    use sui::object_bag::{Self as obag, ObjectBag}; 
    use sui::object::{Self, ID, UID};
    use sui::tx_context::{Self, TxContext};
    
    struct Item has key, store {
        id: UID,
        label: String,
    };

    struct Holder has key {
        id: UID,
        items: ObjectBag<Id, Item>,
    }

    public entry fun add_item(holder: &mut Holder, item: Item) {
        obag::add<ID, Item>(
            &mut hold.items,
            object::id(&item),
            item,
        );
    }

    public entry fun use_item(holder: &Holder, i: ID, j: ID, choice: bool) {
        let item = obag::borrow<ID, Item>(
            &holder.items, 
            if (choice) { i } else { j },
        );

        // use item: &Item
    }
}
4 Likes