1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! AccessControl module.
use crate::modules::{Owner, Whitelist};
use odra::contract_env::caller;
use odra::types::Address;

/// A AccessControl module storage definition.
#[odra::module]
pub struct AccessControl {
    pub owner: Owner,
    pub whitelist: Whitelist,
}

/// Module entrypoints implementation.
#[odra::module]
impl AccessControl {
    /// Module constructor.
    ///
    /// Initializes submodules.
    ///
    /// See [`Owner`] and [`Whitelist`].
    #[odra(init)]
    pub fn init(&mut self, address: Address) {
        self.owner.init(address);
        self.whitelist.add_to_whitelist(address);
    }

    /// Proposes a change of ownership of the contract. Owner will be changed if accepted by propsed
    /// new owner. Only the current owner is permited to call this method.
    ///
    /// # Errors
    /// Throws [`NotAnOwner`](crate::utils::Error::NotAnOwner) if caller
    /// is not the current owner.
    ///
    pub fn propose_new_owner(&mut self, owner: Address) {
        self.owner.ensure_owner();
        self.owner.propose_owner(owner);
    }

    /// Accepts the new owner proposition. This can be called only by the proposed owner.
    ///
    /// # Events
    /// Emits [`OwnerChanged`](crate::modules::owner::events::OwnerChanged),
    /// [`AddedToWhitelist`](crate::modules::whitelist::events::AddedToWhitelist) events.
    pub fn accept_new_owner(&mut self) {
        let caller = caller();
        self.owner.accept_owner(caller);
        self.whitelist.add_to_whitelist(caller);
    }

    /// Adds a new address to the whitelist.
    ///
    /// # Errors
    /// Throws [`NotAnOwner`](crate::utils::Error::NotAnOwner) if the caller
    /// is not the current owner.
    ///
    /// # Events
    /// Emits [`AddedToWhitelist`](crate::modules::whitelist::events::AddedToWhitelist) event.
    pub fn add_to_whitelist(&mut self, address: Address) {
        self.owner.ensure_owner();
        self.whitelist.add_to_whitelist(address);
    }

    /// Removes the `address` from the whitelist.
    ///
    /// # Errors
    /// Throws [`NotAnOwner`](crate::utils::Error::NotAnOwner) if caller
    /// is not the current owner.
    ///
    /// # Events
    /// It emits [`RemovedFromWhitelist`](crate::modules::whitelist::events::RemovedFromWhitelist)
    pub fn remove_from_whitelist(&mut self, address: Address) {
        self.owner.ensure_owner();
        self.whitelist.remove_from_whitelist(address);
    }

    /// Checks whether the given address is added to the whitelist.
    /// See [`Whitelist`].
    pub fn is_whitelisted(&self, address: Address) -> bool {
        self.whitelist.is_whitelisted(address)
    }

    /// Verifies whether the current caller address is added to the whitelist.
    pub fn ensure_whitelisted(&self) {
        self.whitelist.ensure_whitelisted();
    }

    /// Returns the address of the current owner.
    ///
    /// See [`Owner`].
    pub fn get_owner(&self) -> Option<Address> {
        self.owner.get_owner()
    }
}