Skip to content

Commit f9d87eb

Browse files
authored
Merge pull request #70 from OpenZeppelin/stellar-doc-recs
doc recommendations by stellar
2 parents 443f44b + eb925c8 commit f9d87eb

File tree

7 files changed

+374
-204
lines changed

7 files changed

+374
-204
lines changed

content/stellar-contracts/access/access-control.mdx

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,53 @@ The module supports a hierarchical role system where each role can have an "admi
3131

3232
This allows for creating complex organizational structures with chains of command and delegated authority.
3333

34+
#### Setting Up Role Hierarchies
35+
36+
Here's how to establish and use role hierarchies in practice:
37+
38+
```rust
39+
use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Symbol};
40+
use stellar_access::access_control::{self as access_control, AccessControl};
41+
42+
const MANAGER_ROLE: Symbol = symbol_short!("manager");
43+
const GUARDIAN_ROLE: Symbol = symbol_short!("guardian");
44+
45+
#[contract]
46+
pub struct MyContract;
47+
48+
#[contractimpl]
49+
impl MyContract {
50+
pub fn __constructor(e: &Env, admin: Address, manager: Address) {
51+
// Set the contract admin
52+
access_control::set_admin(e, &admin);
53+
54+
// 1. Set MANAGER_ROLE as the admin role for GUARDIAN_ROLE:
55+
// accounts with MANAGER_ROLE can manage accounts with GUARDIAN_ROLE
56+
access_control::set_role_admin_no_auth(e, &admin, &GUARDIAN_ROLE, &MANAGER_ROLE);
57+
58+
// 2. Admin grants MANAGER_ROLE to the manager account
59+
access_control::grant_role_no_auth(e, &admin, &manager, &MANAGER_ROLE);
60+
}
61+
62+
pub fn manage_guardians(e: &Env, manager: Address, guardian1: Address, guardian2: Address) {
63+
// Manager must be authorized
64+
manager.require_auth();
65+
66+
// 3. Now the manager can grant GUARDIAN_ROLE to other accounts
67+
access_control::grant_role_no_auth(e, &manager, &guardian1, &GUARDIAN_ROLE);
68+
access_control::grant_role_no_auth(e, &manager, &guardian2, &GUARDIAN_ROLE);
69+
70+
// Manager can also revoke GUARDIAN_ROLE
71+
access_control::revoke_role_no_auth(e, &manager, &guardian1, &GUARDIAN_ROLE);
72+
}
73+
}
74+
```
75+
76+
In this example:
77+
1. The `admin` sets `MANAGER_ROLE` as the admin role for `GUARDIAN_ROLE` using `set_role_admin()`
78+
2. The `admin` grants the `MANAGER_ROLE` role to the `manager` account
79+
3. The `manager` can now grant/revoke the `GUARDIAN_ROLE` role to other accounts without requiring admin intervention
80+
3481
### Role Enumeration
3582

3683
The system tracks account-role pairs in storage with additional enumeration logic:
@@ -41,6 +88,78 @@ The system tracks account-role pairs in storage with additional enumeration logi
4188

4289
Roles exist only through their relationships with accounts, so a role with zero accounts is indistinguishable from a role that never existed.
4390

91+
## Procedural Macros
92+
93+
The module includes several procedural macros to simplify authorization checks in your contract functions. These macros are divided into two categories:
94+
95+
### Authorization-Enforcing Macros
96+
97+
These macros automatically call `require_auth()` on the specified account before executing the function:
98+
99+
#### @only_admin
100+
101+
Restricts access to the contract admin only:
102+
103+
```rust
104+
#[only_admin]
105+
pub fn admin_function(e: &Env) {
106+
// Only the admin can call this function
107+
// require_auth() is automatically called
108+
}
109+
```
110+
111+
#### @only_role
112+
113+
Restricts access to accounts with a specific role:
114+
115+
```rust
116+
#[only_role(caller, "minter")]
117+
pub fn mint(e: &Env, caller: Address, to: Address, token_id: u32) {
118+
// Only accounts with the "minter" role can call this
119+
// require_auth() is automatically called on caller
120+
}
121+
```
122+
123+
#### @only_any_role
124+
125+
Restricts access to accounts with any of the specified roles:
126+
127+
```rust
128+
#[only_any_role(caller, ["minter", "burner"])]
129+
pub fn multi_role_action(e: &Env, caller: Address) {
130+
// Accounts with either "minter" or "burner" role can call this
131+
// require_auth() is automatically called on caller
132+
}
133+
```
134+
135+
### Role-Checking Macros
136+
137+
These macros check role membership but do **not** enforce authorization. You must manually call `require_auth()` if needed:
138+
139+
#### @has_role
140+
141+
Checks if an account has a specific role:
142+
143+
```rust
144+
#[has_role(caller, "minter")]
145+
pub fn conditional_mint(e: &Env, caller: Address, to: Address, token_id: u32) {
146+
// Checks if caller has "minter" role, but doesn't call require_auth()
147+
caller.require_auth(); // Must manually authorize if needed
148+
}
149+
```
150+
151+
#### @has_any_role
152+
153+
Checks if an account has any of the specified roles:
154+
155+
```rust
156+
#[has_any_role(caller, ["minter", "burner"])]
157+
pub fn multi_role_check(e: &Env, caller: Address) {
158+
// Checks if caller has either role, but doesn't call require_auth()
159+
caller.require_auth(); // Must manually authorize if needed
160+
}
161+
```
162+
44163
## Usage Example
45164

46165
Here’s a simple example of using the Access Control module:

content/stellar-contracts/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Explore our comprehensive suite of secure and scalable smart contract utilities
1818

1919
* **[Pausable](/stellar-contracts/utils/pausable)**: Pause and unpause contract functions, useful for emergency response.
2020
* **[Upgradeable](/stellar-contracts/utils/upgradeable)**: Manage contract upgrades and data migrations seamlessly.
21-
* **[Cryptography](/stellar-contracts/utils/crypto)**: A set of cryptographic primitives and utilities for Soroban contracts.
21+
* **[Cryptography](/stellar-contracts/utils/crypto/crypto)**: A set of cryptographic primitives and utilities for Soroban contracts.
2222

2323
## Security and Audits
2424

content/stellar-contracts/utils/crypto.mdx

Lines changed: 0 additions & 201 deletions
This file was deleted.

0 commit comments

Comments
 (0)