---
title: "Implementing the ID Pointer Pattern"
description: "In this tutorial, we will demonstrate how to implement the ID Pointer pattern in the Sui ecosystem. The ID Pointer pattern separates an object's main data…"
last_updated: 2026-08-21
---

# Implementing the ID Pointer Pattern

In this tutorial, we will demonstrate how to implement the ID Pointer pattern in the Sui ecosystem. The ID Pointer pattern separates an object's main data and its accessors/capabilities by linking the latter to the original. This pattern can be used in various applications, such as issuing transferable capabilities for shared objects, splitting dynamic data and static data, and avoiding unnecessary type linking in generic applications.

For this example, we will implement a simple `Lock` and `Key` mechanics on Sui, where a `Lock<T>` is a shared object that can contain any object, and a `Key` is an owned object required to access the contents of the lock.

Follow these steps to implement the ID Pointer pattern:

1. **Create the lock_and_key module**: Define a new module `examples::lock_and_key` that will implement the ID Pointer pattern.

```rust
module examples::lock_and_key {
    use sui::object::{Self, ID, UID};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};
    use std::option::{Self, Option};
}
```

2. **Define constants and errors**: Define error codes for the lock being empty, the key not matching the lock, and the lock being full.

```rust
const ELockIsEmpty: u64 = 0;
const EKeyMismatch: u64 = 1;
const ELockIsFull: u64 = 2;
```

3. **Define the Lock and Key structs**: Create a `Lock` struct that stores any content inside it and a `Key` struct that is linked to its `Lock` using an `ID` field.

```rust
struct Lock<T: store + key> has key {
    id: UID,
    locked: Option<T>
}

struct Key<phantom T: store + key> has key, store {
    id: UID,
    for: ID,
}
```

4. **Create the key_for function**: Define a public function `key_for` that takes a reference to a `Key<T>` and returns the ID of the associated `Lock`.

```rust
public fun key_for<T: store + key>(key: &Key<T>): ID {
    key.for
}
```

5. **Create the create function**: Define an entry function `create` that takes an object of type `T` and a mutable transaction context as arguments. It creates a new `Lock` with the given object and a `Key` linked to the lock, then transfers the key to the transaction sender.

```rust
public entry fun create<T: store + key>(obj: T, ctx: &mut TxContext) {
    let id = object::new(ctx);
    let for = object::uid_to_inner(&id);

    transfer::share_object(Lock<T> {
        id,
        locked: option::some(obj),
    });

    transfer::transfer(Key<T> {
        for,
        id: object::new(ctx)
    }, tx_context::sender(ctx));
}
```

6. **Create the lock and unlock functions**: Define entry functions `lock` and `unlock` that take an object of type `T`, a mutable reference to a `Lock<T>`, and a reference to a `Key<T>` as arguments. The `lock` function locks the object inside the shared lock if it's empty and the key matches the lock. The `unlock` function unlocks the lock and returns its contents if the key matches the lock and it's not empty.

```rust
public entry fun lock<T: store + key>(
    obj: T,
    lock: &mut Lock<T>,
    key: &Key<T>,
) {
    assert
```
