Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Ownership Library for better UX #204

Merged
merged 6 commits into from
Nov 21, 2023
Merged
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
59 changes: 31 additions & 28 deletions libs/ownership/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,64 @@

# Overview

The Ownership library provides a way to block users other than a single "owner" or "admin" from calling functions. Ownership is often used when needing administrative calls on a contract.
The Ownership library provides a way to block users other than a single "owner" from calling functions. Ownership is often used when needing administrative calls on a contract.

For more information please see the [specification](./SPECIFICATION.md).

# Using the Library

## Getting Started

In order to use the Ownership library it must be added to the Forc.toml file and then imported into your Sway project. To add Sway-libs as a dependency to the Forc.toml file in your project please see the [README.md](../../README.md).
In order to use the Ownership library it must be added to the `Forc.toml` file and then imported into your Sway project. To add Sway-libs as a dependency to the `Forc.toml` file in your project please see the [README.md](../../README.md).

> **NOTE** Until [Issue #5025](https://github.com/FuelLabs/sway/issues/5025) is resolved, in order to use the Ownership Library you must also add the [SRC-5](https://github.com/FuelLabs/sway-standards/tree/master/standards/src_5) standard as a dependencies.

You may import the Ownership library's functionalities like so:

```rust
use ownership::Ownership;
```sway
use ownership::*;
```

Once imported, the `Ownership` struct should be added to the storage block of your contract. There are two approaches when declaring ownership in storage.

1. Initalize the owner on contract deployment by calling the `initialized()` function.

```rust
storage {
owner: Ownership = Ownership::initialized(Identity::Address(Address::from(0x0000000000000000000000000000000000000000000000000000000000000000))),
}
```

2. Leave the owner uninitialized and call the `set_ownership()` function in your own constructor.

```rust
storage {
owner: Ownership = Ownership::uninitialized(),
}
Once imported, the Ownership library's functions will be available. To use them initialize the owner for your contract by calling the `initialize_ownership()` function in your own constructor method.

```sway
#[storage(read, write)]
fn my_constructor(new_owner: Identity) {
storage.owner.set_ownership(new_owner);
initialize_ownership(new_owner);
}
```

> **Note** If this approach is taken, `set_ownership()` **MUST** be called to have a contract owner.

## Basic Functionality

To restrict a function to only the owner, call the `only_owner()` function.

```rust
storage.owner.only_owner();
```sway
only_owner();
// Only the contract's owner may reach this line.
```

To return the owner from storage, call the `owner()` function.
To return the ownership state from storage, call the `_owner()` function.

```rust
let owner: Option<Identity> = storage.owner.owner();
```sway
let owner: State = _owner();
```

## Integrating the Ownership Library into the SRC-5 Standard

To implement the SRC-5 standard with the Ownership library, be sure to add the [SRC-5](https://github.com/FuelLabs/sway-standards/tree/master/standards/src_5) abi to your contract. The following demonstrates the integration of the Ownership library with the SRC-5 standard.

```sway
use ownership::_owner;
use src_5::{State, SRC5};

impl SRC5 for Contract {
#[storage(read)]
fn owner() -> State {
_owner()
}
}
```

> **NOTE** A constructor method must be implemented to initialize the owner.

For more information please see the [specification](./SPECIFICATION.md).
16 changes: 2 additions & 14 deletions libs/ownership/SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,20 @@ The Ownership library can be used anytime a function should be restricted to a s

This function will ensure that the current caller is the owner.

### `owner()`
### `_owner()`

Returns the owner stored in storage.

### `renounce_ownership()`

Only callable by the current owner, this function will remove the owner.

### `set_ownership()`
### `initialize_ownership()`

This function will store a new owner if one has not been set.

### `transfer_ownership()`

Only callable by the current owner, this function will transfer ownership to another user.

### `uninitialized()`

Creates a new ownership in the `Uninitialized` state.

### `initialized()`

Creates a new ownership in the `Initialized` state.

### `revoked()`

Creates a new ownership in the `Revoked` state.

> **Note** Once the ownership has been revoked it cannot be set or transferred again.
4 changes: 1 addition & 3 deletions libs/ownership/src/errors.sw
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
library;

/// Error log for when access is denied.
pub enum AccessError {
pub enum InitializationError {
/// Emiited when an owner has already been set.
CannotReinitialized: (),
/// Emitted when the caller is not the owner of the contract.
NotOwner: (),
}
Loading
Loading