casperlabs_ownable/
ownable.rs

1use crate::alloc::string::ToString;
2use crate::data::{self};
3use alloc::collections::BTreeMap;
4use alloc::{string::String, vec::Vec};
5use casper_contract::contract_api::runtime;
6use casper_contract::contract_api::storage;
7use casper_types::{ApiError, ContractHash, ContractPackageHash, Key, URef};
8use casperlabs_contract_utils::{ContractContext, ContractStorage};
9//Events
10
11#[repr(u16)]
12pub enum Error {
13    /// 65,546 for (Ownable: caller is not the owner)
14    OwnableNotOwner = 11501,
15    /// 65,540 for (Ownable: new owner is the zero address)
16    OwnableNewOwnerAddressZero = 11502,
17}
18
19impl From<Error> for ApiError {
20    fn from(error: Error) -> ApiError {
21        ApiError::User(error as u16)
22    }
23}
24
25pub enum OwnableEvent {
26    OwnershipTransferred { previous_owner: Key, new_owner: Key },
27}
28
29impl OwnableEvent {
30    pub fn type_name(&self) -> String {
31        match self {
32            OwnableEvent::OwnershipTransferred {
33                previous_owner: _,
34                new_owner: _,
35            } => "OwnershipTransferred",
36        }
37        .to_string()
38    }
39}
40pub trait OWNABLE<Storage: ContractStorage>: ContractContext<Storage> {
41    fn init(&mut self, contract_hash: ContractHash, package_hash: ContractPackageHash) {
42        data::set_owner(self.get_caller());
43        data::set_hash(contract_hash);
44        data::set_package_hash(package_hash);
45        self.ownable_emit(&OwnableEvent::OwnershipTransferred {
46            previous_owner: data::zero_address(),
47            new_owner: data::get_owner(),
48        });
49    }
50    // @dev Returns the address of the current owner.
51    fn owner(&self) -> Key {
52        return data::get_owner();
53    }
54    // @dev Throws if called by any account other than the owner.
55    fn only_owner(&self) {
56        if !(self.is_owner()) {
57            runtime::revert(ApiError::from(Error::OwnableNotOwner));
58        }
59    }
60    // @dev Returns true if the caller is the current owner.
61    fn is_owner(&self) -> bool {
62        return self.get_caller() == data::get_owner();
63    }
64    // * @dev Leaves the contract without owner. It will not be possible to call
65    // * `onlyOwner` functions anymore. Can only be called by the current owner.
66    // *
67    // * NOTE: Renouncing ownership will leave the contract without an owner,
68    // * thereby removing any functionality that is only available to the owner.
69    fn renounce_ownership(&mut self) {
70        self.only_owner();
71        self.ownable_emit(&OwnableEvent::OwnershipTransferred {
72            previous_owner: data::get_owner(),
73            new_owner: data::zero_address(),
74        });
75        data::set_owner(data::zero_address());
76    }
77    // * @dev Transfers ownership of the contract to a new account (`newOwner`).
78    // * Can only be called by the current owner.
79    fn transfer_ownership(&mut self, new_owner: Key) {
80        self.only_owner();
81        self._transfer_ownership(new_owner);
82    }
83    fn _transfer_ownership(&mut self, new_owner: Key) {
84        if !(new_owner != data::zero_address()) {
85            runtime::revert(ApiError::from(Error::OwnableNewOwnerAddressZero));
86        }
87        self.ownable_emit(&OwnableEvent::OwnershipTransferred {
88            previous_owner: data::get_owner(),
89            new_owner: new_owner,
90        });
91        data::set_owner(new_owner);
92    }
93
94    fn ownable_emit(&mut self, ownable_event: &OwnableEvent) {
95        let mut events = Vec::new();
96        let package = data::get_package_hash();
97        match ownable_event {
98            OwnableEvent::OwnershipTransferred {
99                previous_owner,
100                new_owner,
101            } => {
102                let mut event = BTreeMap::new();
103                event.insert("contract_package_hash", package.to_string());
104                event.insert("event_type", ownable_event.type_name());
105                event.insert("previous_owner", previous_owner.to_string());
106                event.insert("new_owner", new_owner.to_string());
107                events.push(event);
108            }
109        };
110        for event in events {
111            let _: URef = storage::new_uref(event);
112        }
113    }
114}