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
//! The Owner module.
use crate::modules::owner::events::OwnerChanged;
use crate::utils::Error;
use odra::contract_env::{caller, revert};
use odra::types::event::OdraEvent;
use odra::types::Address;
use odra::Variable;

#[odra::module]
pub struct Owner {
    pub owner: Variable<Address>,
    pub proposed_owner: Variable<Option<Address>>,
}

/// Module entrypoints implementation.
#[odra::module]
impl Owner {
    /// Initialize the module.
    #[odra(init)]
    pub fn init(&mut self, owner: Address) {
        self.change_ownership(owner);
    }

    /// Sets a new owner proposition.
    pub fn propose_owner(&mut self, owner: Address) {
        self.proposed_owner.set(Some(owner));
    }

    /// Accepts the new owner proposition.
    pub fn accept_owner(&mut self, caller: Address) {
        if let Some(proposed_owner) = self.proposed_owner.get_or_default() {
            if proposed_owner != caller {
                revert(Error::NotAProposedOwner);
            }
            self.change_ownership(proposed_owner);
        } else {
            revert(Error::NoProposedOwner);
        }
    }

    /// Set the owner to the new address.
    pub fn change_ownership(&mut self, owner: Address) {
        self.owner.set(owner);
        self.proposed_owner.set(None);

        OwnerChanged { new_owner: owner }.emit();
    }

    /// Verify if the contract caller is the owner. Revert otherwise.
    pub fn ensure_owner(&self) {
        if let Some(owner) = self.owner.get() {
            if owner != caller() {
                revert(Error::NotAnOwner)
            }
        } else {
            revert(Error::OwnerIsNotInitialized) // Owner is not initialized.
        }
    }

    pub fn get_owner(&self) -> Option<Address> {
        self.owner.get()
    }
}
pub mod events {
    //! Events definitions.
    use odra::types::Address;
    use odra::Event;

    /// Event emitted when the owner change.
    #[derive(Debug, PartialEq, Eq, Event)]
    pub struct OwnerChanged {
        pub new_owner: Address,
    }
}