casperlabs_contract_utils/
admin_control.rs

1use casper_contract::{
2    contract_api::{runtime, storage},
3    unwrap_or_revert::UnwrapOrRevert,
4};
5use casper_types::{ApiError, Key};
6
7use crate::{ContractContext, ContractStorage, Dict};
8
9const ADMINS_DICT: &str = "admins";
10
11pub trait AdminControl<Storage: ContractStorage>: ContractContext<Storage> {
12    fn init(&mut self) {
13        Admins::init();
14    }
15
16    fn add_admin(&mut self, address: Key) {
17        self.assert_caller_is_admin();
18        self.add_admin_without_checked(address);
19    }
20
21    fn disable_admin(&mut self, address: Key) {
22        self.assert_caller_is_admin();
23        Admins::instance().disable_admin(&address);
24    }
25
26    fn add_admin_without_checked(&mut self, address: Key) {
27        Admins::instance().add_admin(&address);
28    }
29
30    fn assert_caller_is_admin(&self) {
31        let caller = self.get_caller();
32        if !Admins::instance().is_admin(&caller) {
33            runtime::revert(ApiError::User(20));
34        }
35    }
36}
37
38struct Admins {
39    dict: Dict,
40}
41
42impl Admins {
43    pub fn instance() -> Admins {
44        Admins {
45            dict: Dict::instance(ADMINS_DICT),
46        }
47    }
48    pub fn init() {
49        storage::new_dictionary(ADMINS_DICT).unwrap_or_revert();
50    }
51
52    pub fn is_admin(&self, key: &Key) -> bool {
53        self.dict.get_by_key::<()>(key).is_some()
54    }
55
56    pub fn add_admin(&self, key: &Key) {
57        self.dict.set_by_key(key, ());
58    }
59
60    pub fn disable_admin(&self, key: &Key) {
61        self.dict.remove_by_key::<()>(key);
62    }
63}