Sui.

Post

Share your knowledge.

Owen.
Owen486
Jun 11, 2025
Expert Q&A

How to update a merchant's key in ObjectTable when it changes in the struct?

Hi everyone, I'm just getting started with writing smart contracts and I'm working on my very first project. I'd love some help with an issue I'm stuck on.

So far, I’ve created a Merchant struct that looks like this:

  • id: a unique identifier (UID)
  • owner: the address of the merchant
  • key: a String used as a unique key
  • balance: a u64 representing their balance

I also made a MerchantRegistry struct to manage all merchants:

  • id: another UID
  • merchant_to_address: an ObjectTable<address, Merchant> mapping addresses to merchants
  • merchant_to_key: an ObjectTable<String, Merchant> mapping keys to merchants

I want to be able to look up a merchant either by their address or by their key.

When a user updates their key inside the Merchant struct, the change doesn’t automatically update the key in the merchant_to_key table. That means the old key still points to the merchant, which breaks things.

I tried removing the entry from the table and inserting it back with the new key, but I keep running into errors like:

"Cannot ignore values without drop ability"

I'm pretty sure this is a beginner mistake, but I haven't been able to find a clear explanation or solution anywhere. Is there a proper way to handle updating the key in both the struct and the lookup table?

  • Sui
  • Move
5
1
Share
Comments
.

Answers

1
24p30p.
Jul 9 2025, 05:43

If you’re trying to update a merchant’s key in a ObjectTable<String, Merchant> and running into errors like “Cannot ignore values without drop ability,” the issue is that in Sui Move, you can’t just delete or replace objects in storage without explicitly handling ownership and types that lack the drop ability. When you change the key inside your Merchant struct, that doesn't automatically update the merchant_to_key table—so you end up with the old key still pointing to the object, while the new key isn't linked at all.

To fix this, you need to manually remove the old entry, update the struct, and then reinsert it using the new key. But because the Merchant struct doesn't have the drop ability, you can't just remove it and ignore the result—you have to store and reuse the returned object. Here's how you can do it properly inside a transaction:

public entry fun update_merchant_key(
    registry: &mut MerchantRegistry,
    old_key: String,
    new_key: String
) {
    // Remove the merchant using the old key and store the returned object
    let merchant = object_table::remove(&mut registry.merchant_to_key, old_key);

    // Update the key field inside the struct
    merchant.key = new_key;

    // Re-insert into the table with the updated key
    object_table::add(&mut registry.merchant_to_key, new_key, merchant);
}

This way, you safely extract the merchant, modify it, and insert it back using the new key—all while respecting Move's ownership rules.

Remember, this is necessary because Move is designed to prevent accidentally dropping or leaking resources. If your Merchant struct doesn't have the drop ability (which is common when it contains a UID), you must always handle it explicitly.

To get a clearer idea of how ObjectTable works and how to handle ownership safely, check the official docs here: https://docs.sui.io/build/move/object-tables.

0
Comments
.

Do you know the answer?

Please log in and share it.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

432Posts640Answers
Sui.X.Peera.

Earn Your Share of 1000 Sui

Gain Reputation Points & Get Rewards for Helping the Sui Community Grow.

Reward CampaignJuly