mod storage;
#[cfg(test)]
mod test;
use soroban_sdk::{contracterror, contractevent, contracttrait, Address, Env, Symbol, Vec};
pub use crate::access_control::storage::{
accept_admin_transfer, add_to_role_enumeration, enforce_admin_auth,
ensure_if_admin_or_admin_role, ensure_role, get_admin, get_existing_roles, get_role_admin,
get_role_member, get_role_member_count, grant_role, grant_role_no_auth, has_role,
remove_from_role_enumeration, remove_role_accounts_count_no_auth, remove_role_admin_no_auth,
renounce_admin, renounce_role, revoke_role, revoke_role_no_auth, set_admin, set_role_admin,
set_role_admin_no_auth, transfer_admin_role, AccessControlStorageKey,
};
#[contracttrait]
pub trait AccessControl {
fn has_role(e: &Env, account: Address, role: Symbol) -> Option<u32> {
storage::has_role(e, &account, &role)
}
fn get_existing_roles(e: &Env) -> Vec<Symbol> {
storage::get_existing_roles(e)
}
fn get_role_member_count(e: &Env, role: Symbol) -> u32 {
storage::get_role_member_count(e, &role)
}
fn get_role_member(e: &Env, role: Symbol, index: u32) -> Address {
storage::get_role_member(e, &role, index)
}
fn get_role_admin(e: &Env, role: Symbol) -> Option<Symbol> {
storage::get_role_admin(e, &role)
}
fn get_admin(e: &Env) -> Option<Address> {
storage::get_admin(e)
}
fn grant_role(e: &Env, account: Address, role: Symbol, caller: Address) {
storage::grant_role(e, &account, &role, &caller);
}
fn revoke_role(e: &Env, account: Address, role: Symbol, caller: Address) {
storage::revoke_role(e, &account, &role, &caller);
}
fn renounce_role(e: &Env, role: Symbol, caller: Address) {
storage::renounce_role(e, &role, &caller);
}
fn transfer_admin_role(e: &Env, new_admin: Address, live_until_ledger: u32) {
storage::transfer_admin_role(e, &new_admin, live_until_ledger);
}
fn accept_admin_transfer(e: &Env) {
storage::accept_admin_transfer(e);
}
fn set_role_admin(e: &Env, role: Symbol, admin_role: Symbol) {
storage::set_role_admin(e, &role, &admin_role);
}
fn renounce_admin(e: &Env) {
storage::renounce_admin(e);
}
}
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
pub enum AccessControlError {
Unauthorized = 2000,
AdminNotSet = 2001,
IndexOutOfBounds = 2002,
AdminRoleNotFound = 2003,
RoleCountIsNotZero = 2004,
RoleNotFound = 2005,
AdminAlreadySet = 2006,
RoleNotHeld = 2007,
RoleIsEmpty = 2008,
TransferInProgress = 2009,
MaxRolesExceeded = 2010,
}
const DAY_IN_LEDGERS: u32 = 17280;
pub const ROLE_EXTEND_AMOUNT: u32 = 90 * DAY_IN_LEDGERS;
pub const ROLE_TTL_THRESHOLD: u32 = ROLE_EXTEND_AMOUNT - DAY_IN_LEDGERS;
pub const MAX_ROLES: u32 = 256;
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoleGranted {
#[topic]
pub role: Symbol,
#[topic]
pub account: Address,
pub caller: Address,
}
pub fn emit_role_granted(e: &Env, role: &Symbol, account: &Address, caller: &Address) {
RoleGranted { role: role.clone(), account: account.clone(), caller: caller.clone() }.publish(e);
}
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoleRevoked {
#[topic]
pub role: Symbol,
#[topic]
pub account: Address,
pub caller: Address,
}
pub fn emit_role_revoked(e: &Env, role: &Symbol, account: &Address, caller: &Address) {
RoleRevoked { role: role.clone(), account: account.clone(), caller: caller.clone() }.publish(e);
}
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoleAdminChanged {
#[topic]
pub role: Symbol,
pub previous_admin_role: Symbol,
pub new_admin_role: Symbol,
}
pub fn emit_role_admin_changed(
e: &Env,
role: &Symbol,
previous_admin_role: &Symbol,
new_admin_role: &Symbol,
) {
RoleAdminChanged {
role: role.clone(),
previous_admin_role: previous_admin_role.clone(),
new_admin_role: new_admin_role.clone(),
}
.publish(e);
}
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AdminTransferInitiated {
#[topic]
pub current_admin: Address,
pub new_admin: Address,
pub live_until_ledger: u32,
}
pub fn emit_admin_transfer_initiated(
e: &Env,
current_admin: &Address,
new_admin: &Address,
live_until_ledger: u32,
) {
AdminTransferInitiated {
current_admin: current_admin.clone(),
new_admin: new_admin.clone(),
live_until_ledger,
}
.publish(e);
}
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AdminTransferCompleted {
#[topic]
pub new_admin: Address,
pub previous_admin: Address,
}
pub fn emit_admin_transfer_completed(e: &Env, previous_admin: &Address, new_admin: &Address) {
AdminTransferCompleted { new_admin: new_admin.clone(), previous_admin: previous_admin.clone() }
.publish(e);
}
#[contractevent]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AdminRenounced {
#[topic]
pub admin: Address,
}
pub fn emit_admin_renounced(e: &Env, admin: &Address) {
AdminRenounced { admin: admin.clone() }.publish(e);
}