Sui.

Post

Share your knowledge.

article banner.
harry phan.
Apr 12, 2025
Article

✏️Parent-Child Objects in Sui Move

In Sui Move, objects can own other objects just like accounts own objects. This opens up new design patterns (and a few gotchas) for developers. In this guide, I’ll break down parent-child object concepts in Sui Move into four parts:

  1. Intro to Parent-Child Concepts in Sui Move
  2. Object Access Control & receive Mechanics
  3. Cross-Module Child Management with public_receive
  4. Soul-Binding Logic & ReturnReceipt Pattern

By the end, you’ll understand how to nest objects, retrieve child objects via transfer::receive, manage children across modules with public_receive, and even create soul-bound objects that boomerang back to their owner.

Intro to Parent-Child Concepts in Sui Move

What Are Parent and Child Objects?

 In Sui, every object has a unique ID and an owner. Usually the owner is an address (like a user’s account), but the owner can also be another object.

If object A owns object B, we call A the parent and B the child. The child is object-owned rather than address-owned.

Transferring to objects: Sui doesn’t actually distinguish between an address and an object ID under the hood – both are just 32-byte identifiers This means you can transfer an object to another object’s ID in the same way you’d transfer to a user’s address. When you do this, you’re effectively nesting an object inside a parent object. Sui’s runtime sets the child’s owner field to the parent’s ID (instead of an address)

So why is this cool?

Because the child keeps its own unique ID and exists independently in storage, but now it’s tied to the parent. It’s like giving your friend a unique collectible to hold in their locker – the collectible keeps its ID and can be tracked, but your friend’s locker is now listed as its owner.

It’s important to distinguish Unique vs. nested vs. child objects: 

  • Unique Object (Address-Owned): A regular object owned by an address (e.g. a user’s account). This is the default case – think NFTs, coins, etc., living directly in a user’s wallet. Each has a unique ID and is top-level in storage.
  • Nested (Wrapped) Object: An object that is stored inside another object’s data (for example, as a field in a struct). In this case, the inner object is wrapped and not a separate top-level entity. It doesn’t show up by its ID in global storage because it’s part of the parent’s byte content. In Sui, if you put an object as a field in another without special handling, it becomes wrapped.
  • Child Object (Object-Owned): An object that is owned by another object but not directly wrapped in its fields. The child remains a separate top-level object in storage (with its own ID and data), and the parent’s ID is recorded as the owner in the child’s metadata . This means you can query or access the child by its ID (with the right permissions). It’s not physically embedded in the parent’s contents, just logically owned. Using our analogy, it’s like you gave your friend your collectible to hold – it’s still individually tagged and trackable, just stored in their locker.

The benefit of making a child object (via transfer) instead of wrapping it is that the child’s ID remains accessible externally. For example, explorers or wallets can list a child object by ID, whereas a wrapped object is invisible outside its parent.

Child objects also maintain stable IDs even as they move between owners or get nested in different parents . This is great for things like on-chain inventory or “wallet inside a wallet” patterns, where you want a container object to hold many items that others can still reference individually

Ownership and access: If an object is owned by another object, only the owner of the parent can typically access or use the child This is a form of dynamic authorization. For instance, if Alice owns a parent object P, and P owns child C, then only Alice (or transactions Alice signs) can manipulate C. Sui enforces this so that owning a parent is like holding the keys to all its children 🔑.

Maybe you know:

Sui’s transfer-to-object feature essentially gives us tree-like object ownership. A parent can have many children (and those children can have their own children, forming a hierarchy). This is done by treating object IDs like addresses for transfers. We have:

  • Address-owned objects (normal unique objects),
  • Object-owned objects (child objects, still top-level but tied to a parent),
  • Wrapped objects (nested inside another object’s data, not top-level).

In the next articles, we’ll see how to actually retrieve or interact with child objects (since they aren’t directly accessible like address-owned ones) and how to enforce rules around them.

  • Sui
  • Move
3
Share
Comments
.
We use cookies to ensure you get the best experience on our website.
More info