What is the motivation to use ownership from sway-libs?
Hi friends, I have decided to integrate the ownership library with the src-5 standard and I have a question what is the advantage of using this approach over my previous one?
My previous approach
Forc.toml
[project]
authors = ["Alex"]
entry = "main.sw"
license = "Apache-2.0"
name = "ownership-example"
[dependencies]
main.sw
contract;
use std::constants::{ZERO_B256};
configurable {
OWNER: b256 = ZERO_B256,
}
storage {
/// Keeps track of users with admin access to the contract.
admins: StorageMap<Address, bool> = StorageMap {},
}
/*...SOME CODE HERE...*/
impl OwnershipExampleContract for Contract {
/*...SOME CODE HERE...*/
/// Adds an admin to the platform, can only be called by the owner.
///
/// # Arguments
///
/// * `address`: [Address] - The address of the new admin to be added.
#[storage(write)]
fn add_admin(address: Address){
verify_owner();
storage.admins.insert(address, true);
}
/// Removes an admin from the platform, can only be called by the owner.
///
/// # Arguments
///
/// * `address`: [Address] - The address of the admin to be removed.
#[storage(write)]
fn remove_admin(address: Address){
verify_owner();
storage.admins.insert(address, false);
}
}
/// Verifies if the caller is the owner.
fn verify_owner() {
require(OWNER != ZERO_B256 && msg_sender_address().into() == OWNER, "Access denied");
}
/// Verifies if the caller is the owner or an admin.
#[storage(read)]
fn verify_owner_or_admin() {
let caller = msg_sender_address();
let is_owner = OWNER != ZERO_B256 && caller.into() == OWNER;
let is_admin = storage.admins.get(caller).try_read().unwrap_or(false);
require(is_owner || is_admin, "Access denied");
}
src-5 + owbership approach
Forc.toml
[project]
authors = ["Alex"]
entry = "main.sw"
license = "Apache-2.0"
name = "ownership-example"
[dependencies]
ownership = { git = "https://github.com/FuelLabs/sway-libs" }
src_5 = { git = "https://github.com/FuelLabs/sway-standards" }
main.sw
contract;
use src_5::{Ownership, State};
use ownership::*;
// fixme: setup OWNER: Address in rust sdk
// https://forum.fuel.network/t/no-configurable-field-in-abi-pyth-oracle-contract/3397
// https://github.com/FuelLabs/sway/issues/5242
configurable {
OWNER: Address = Address::from(0x09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db),
}
storage {
/// Ownership information for controlling access to Spark Contracts management functions.
owner: Ownership = Ownership::initialized(Identity::Address(OWNER)),
/// Keeps track of users with admin access to the contract.
admins: StorageMap<Address, bool> = StorageMap {},
}
/*...SOME CODE HERE...*/
impl OwnershipExampleContract for Contract {
/*...SOME CODE HERE...*/
/// Adds an admin to the platform, can only be called by the owner.
///
/// # Arguments
///
/// * `address`: [Address] - The address of the new admin to be added.
#[storage(write)]
fn add_admin(address: Address){
storage.owner.only_owner();
storage.admins.insert(address, true);
}
/// Removes an admin from the platform, can only be called by the owner.
///
/// # Arguments
///
/// * `address`: [Address] - The address of the admin to be removed.
#[storage(write)]
fn remove_admin(address: Address){
storage.owner.only_owner();
storage.admins.insert(address, false);
}
}
/// Retrieves the message sender's address, reverting if not found or not an address.
///
/// # Returns
///
/// * [Address] - address of the message sender.
pub fn msg_sender_address() -> Address {
match std::auth::msg_sender().unwrap() {
Identity::Address(identity) => identity,
_ => revert(0),
}
}
/// Verifies if the message sender is either the owner or an admin of the contract.
#[storage(read)]
fn verify_owner_or_admin() {
let caller = msg_sender_address();
let is_owner = match storage.owner.owner() {
State::Initialized(owner) => owner == Identity::Address(caller),
_ => false,
};
let is_admin = storage.admins.get(caller).try_read().unwrap_or(false);
require(is_owner || is_admin, "Access denied");
}
You can compare these 2 snippets. For me personally I realized that using src-5 approach is not so convenient because I have to connect 2 additional dependencies and there is no possibility to install OWNER via configurable
Let’s please discuss here how we can realize implementation of ownership simpler and please pay attention to these issues: