Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions content/contracts-sui/1.x/access-control.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: RBAC
---

<Callout type="warn">
The example code snippets used in this guide are experimental and have not been audited. They simply help exemplify usage of the OpenZeppelin Sui Package.
</Callout>

The `access_control` module provides role-based authorization for Sui Move packages. It is the right choice when authority is not a single transferable object, or when several privileged actors need different permissions over shared protocol state.

## Use cases

Use `access_control` when your protocol needs:

- A root role controlled by a package One-Time Witness (OTW).
- Operational roles such as admin, treasurer, operator, guardian, pauser, or keeper.
- Role-admin relationships, where one role grants and revokes another.
- Typed authorization proofs with `Auth<Role>` for new functions.
- Signature-preserving checks with `assert_has_role` for existing public functions.
- Delayed root-role transfer to governance or a multisig.
- Delayed root-role renounce when the protocol should be permanently locked.
- Delayed changes to the root-role transfer and renounce delay.

## Import

```move
use openzeppelin_access::access_control::{Self, AccessControl, Auth};
```

## Default pattern

The central object is `AccessControl<RootRole>`. For new code, publish it as a standalone shared object and pass it directly in PTBs. Protected functions receive `&Auth<Role>` instead of storing the registry inside the protected object.

```move
module my_sui_app::roles;

use openzeppelin_access::access_control::{Self, Auth};

public struct ROLES has drop {}

public struct OperatorRole {}
public struct Treasury has key, store { id: UID }

const DEFAULT_ADMIN_DELAY_MS: u64 = 24 * 60 * 60 * 1_000;

fun init(otw: ROLES, ctx: &mut TxContext) {
let mut access = access_control::new(otw, DEFAULT_ADMIN_DELAY_MS, ctx);
access.grant_role<_, OperatorRole>(ctx.sender(), ctx);

transfer::public_share_object(access);
transfer::share_object(Treasury { id: object::new(ctx) });
}

public fun protected_action(_: &mut Treasury, _: &Auth<OperatorRole>) {
// Authorized by Auth<OperatorRole>.
}
```

<Callout type="warn">
The root role cannot be granted, revoked, or renounced with ordinary role-management calls. Use the delayed root transfer or delayed root renounce flows instead. Finalizing a root renounce leaves the registry without a root holder, so use it only when the protocol should become permanently unmanaged.
</Callout>

## Root role operations

The root role is the fallback admin for every role. Because it can recover role administration, root-role changes go through delayed flows:

- `begin_default_admin_transfer` schedules transfer to a new root holder.
- `accept_default_admin_transfer` lets the pending holder accept after the configured delay.
- `begin_default_admin_renounce` schedules an intentional lock-in where the current root holder gives up the root role.
- `accept_default_admin_renounce` finalizes that lock-in after the configured delay.
- `cancel_default_admin_transfer` cancels either a pending transfer or a pending renounce.
- `begin_default_admin_delay_change`, `accept_default_admin_delay_change`, and `cancel_default_admin_delay_change` manage the delay itself.

Role grants and root transfers reject `@0x0`. Use the delayed root-renounce flow when the goal is to intentionally lock the registry.

## Authorization styles

Use `Auth<Role>` for new functions when you want authorization to be explicit in the function type and reusable across multiple calls in the same PTB.

Because `Auth<Role>` is minted from the singleton registry for that role's home module, protected functions do not need to compare registry object IDs when they receive `&Auth<Role>`.

Use `assert_has_role` when you are retrofitting an existing public function and changing the signature would be disruptive or invalid for package-upgrade compatibility. In that case, the registry is usually stored under an existing `Config` or `State` object and borrowed internally.

## Learn more

For a full walkthrough of roles, `Auth<Role>`, publishing, upgrades, and PTB usage, see the [Role Based Access Control guide](/contracts-sui/1.x/guides/access-control).

For function-level signatures, events, and errors, see the [Access API reference](/contracts-sui/1.x/api/access).
352 changes: 29 additions & 323 deletions content/contracts-sui/1.x/access.mdx

Large diffs are not rendered by default.

Loading
Loading