Post
Share your knowledge.
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 merchantkey
: a String used as a unique keybalance
: a u64 representing their balance
I also made a MerchantRegistry
struct to manage all merchants:
id
: another UIDmerchant_to_address
: anObjectTable<address, Merchant>
mapping addresses to merchantsmerchant_to_key
: anObjectTable<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
Answers
1If 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.
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.
- Why does BCS require exact field order for deserialization when Move structs have named fields?53
- Multiple Source Verification Errors" in Sui Move Module Publications - Automated Error Resolution43
- Sui Transaction Failing: Objects Reserved for Another Transaction25
- How do ability constraints interact with dynamic fields in heterogeneous collections?05