> For the complete documentation index, see [llms.txt](/llms.txt)

# Derived Objects

Compute derived object IDs from parent objects for deterministic offline derivation.



Derived objects enable deterministic IDs for objects, enabling offline derivation of object IDs.
[Click here to read more.](https://docs.sui.io/concepts/sui-move-concepts/derived-objects)

To derive an object ID, you can import `deriveObjectID` function exposed from utils.

```typescript
import { deriveObjectID } from '@mysten/sui/utils';
```

To derive any object, you need to have its parent's ID (the object from which it was derived), and
the key used to generate it.

<Callout type="warn">
  It is recommended to verify the onchain `derived_object::derive_address` match your offchain
  calculation (at least once when implementing offline calculations), especially for critical cases
  like transferring assets.
</Callout>

## Deriving using primitive keys

To derive the IDs using primitive types, you can use the built-in types like this, assuming you have
a parent object with ID `0xc0ffee`.

```typescript
// Example 1: Onchain derivation for `0xc0ffee + vector<u8>([0,1,2])
deriveObjectID('0xc0ffee', 'vector<u8>', bcs.vector(bcs.u8()).serialize([0, 1, 2]).toBytes());

// Example 2: Onchain derivation for `0xc0ffee + address('0x111')`
deriveObjectID('0xc0ffee', 'address', bcs.Address.serialize('0x111').toBytes());

// Example 3: Onchain derivation for `0xc0ffee + non-ascii string ("foo")`
deriveObjectID('0xc0ffee', '0x1::string::String', bcs.String.serialize('foo').toBytes());
```

## Deriving using custom types

To derive IDs using your custom objects, you can use BCS and the known type IDs.

Assuming a custom struct onchain (for the key) being:

```move
public struct DemoStruct has copy, store, drop { value: u64 }
```

you can derive it by doing:

```typescript
// Assuming we wanted to derive for key `DemoStruct { value: 1 }`.
const bcsType = bcs.struct('DemoStruct', {
	value: bcs.u64(),
});

const key = bcsType.serialize({ value: 1 }).toBytes();

// Derive the object ID for the key `DemoStruct { value: 1 }`.
deriveObjectID('0xc0ffee', `0xc0ffee::demo::DemoStruct`, key);
```

### Deriving with fieldless structs

In Move, structs with no user-defined fields automatically get a `dummy_field: bool` injected by the
compiler. This means their BCS encoding is not empty. It is a single `0x00` byte (the encoding of
`false`). You can treat this as a constant.

A real-world example is `0x2::coin_registry::CurrencyKey<T>`, which is a fieldless generic struct
used to derive `Currency` objects from the coin registry (`0xc`) based on their type:

```typescript
// Onchain: `public struct CurrencyKey<phantom T>() has copy, store, drop`
// The compiler injects `dummy_field: bool`, always `false`.
const key = new Uint8Array([0]);

const coinType = '0x2::sui::SUI';
const currencyId = deriveObjectID('0xc', `0x2::coin_registry::CurrencyKey<${coinType}>`, key);
```

This applies to any struct with no fields. Phantom type parameters do not add any BCS-encoded data,
so the key is always `new Uint8Array([0])`.
