api3_common/
access.rs

1use crate::abi::Token;
2use crate::{ensure, keccak_packed, Bytes32, Error, Zero};
3
4/// Roles that are known at dev time.
5pub enum StaticRole {
6    UnlimitedReaderRole,
7    NameSetterRole,
8}
9
10pub trait AccessControlRegistryAdminnedWithManager {
11    type Address: AsRef<[u8]> + Zero + PartialEq;
12
13    /// Get the manager of this registry
14    fn manager(&self) -> &Self::Address;
15    /// Admin role description
16    fn admin_role_description(&self) -> String;
17    /// Admin role description hash
18    fn admin_role_description_hash(&self) -> Bytes32;
19    /// Admin role
20    fn admin_role(&self) -> Bytes32;
21}
22
23/// The access control registry interface in the solidity contract
24pub trait AccessControlRegistry: AccessControlRegistryAdminnedWithManager {
25    /// Default admin role, align with Openzepplin's definition
26    const DEFAULT_ADMIN_ROLE: Bytes32 = [0; 32];
27    const NAME_SETTER_ROLE_DESCRIPTION: &'static str = "Name setter";
28    const UNLIMITED_READER_ROLE_DESCRIPTION: &'static str = "Unlimited reader";
29
30    /// Find the role by its name. Not in the original solidity contract
31    /// Just for making it work in Rust
32    fn find_static_role(&self, role: StaticRole) -> Bytes32 {
33        match role {
34            StaticRole::UnlimitedReaderRole => self.derive_role(
35                self.derive_admin_role(self.manager()),
36                Self::UNLIMITED_READER_ROLE_DESCRIPTION.parse().unwrap(),
37            ),
38            StaticRole::NameSetterRole => self.derive_role(
39                self.derive_admin_role(self.manager()),
40                Self::NAME_SETTER_ROLE_DESCRIPTION.parse().unwrap(),
41            ),
42        }
43    }
44    /// Checks that an account has a specific role. Reverts
45    /// with a standardized message including the required role.
46    /// `role` The role to check
47    /// `msg_sender` The address to check
48    fn only_role(&self, role: &Bytes32, msg_sender: &Self::Address) -> Result<(), Error> {
49        ensure!(
50            self.has_role(
51                &self.get_role_admin(role).ok_or(Error::RoleAdminNotFound)?,
52                msg_sender
53            ),
54            Error::NotAuthorized
55        )
56    }
57    /// Checks if user has a particular role
58    /// `role` The role to check
59    /// `who` The address to check
60    fn has_role(&self, role: &Bytes32, who: &Self::Address) -> bool;
61    /// Grant role for the user
62    /// `role` The role to grant
63    /// `who` The address to grant role
64    fn grant_role(&mut self, role: &Bytes32, who: &Self::Address) -> Result<(), Error>;
65    /// Get the admin role of role
66    /// `role` The role to check
67    fn get_role_admin(&self, role: &Bytes32) -> Option<Bytes32>;
68    /// Set the role admin for a role
69    /// `role` The role to grant
70    /// `role_admin` The role admin
71    fn set_role_admin(&mut self, role: &Bytes32, role_admin: Bytes32) -> Result<(), Error>;
72    /// Called by the account to renounce the role
73    /// Override to disallow managers to renounce their root roles.
74    /// `role` Role to be renounced
75    /// `account` Account to renounce the role
76    fn renounce_role(&mut self, role: &Bytes32, account: &Self::Address) -> Result<(), Error>;
77    /// Called by the role admin to renounce the role
78    /// Override to disallow managers to renounce their root roles.
79    /// `role` Role to be renounced
80    /// `account` Account to renounce the role
81    fn revoke_role(&mut self, role: &Bytes32, account: &Self::Address) -> Result<(), Error>;
82    /// Initializes the manager by initializing its root role and
83    /// granting it to them
84    /// Anyone can initialize a manager. An uninitialized manager
85    /// attempting to initialize a role will be initialized automatically.
86    /// Once a manager is initialized, subsequent initializations have no
87    /// effect.
88    /// `manager` Manager address to be initialized
89    fn initialize_manager(&mut self, manager: &Self::Address) -> Result<(), Error> {
90        ensure!(!manager.is_zero(), Error::InvalidAddress)?;
91        let root_role = RoleDeriver::derive_root_role(manager.as_ref());
92        if !self.has_role(&root_role, manager) {
93            self.grant_role(&root_role, manager)?;
94        }
95        Ok(())
96    }
97    /// Initializes a role by setting its admin role and grants it to
98    /// the sender
99    /// If the sender should not have the initialized role, they should
100    /// explicitly renounce it after initializing it.
101    /// Once a role is initialized, subsequent initializations have no effect
102    /// other than granting the role to the sender.
103    /// The sender must be a member of `admin_role`. `admin_role` value is not
104    /// validated because the sender cannot have the `bytes32(0)` role.
105    /// If the sender is an uninitialized manager that is initializing a role
106    /// directly under their root role, manager initialization will happen
107    /// automatically, which will grant the sender `admin_role` and allow them
108    /// to initialize the role.
109    /// `admin_role` Admin role to be assigned to the initialized role
110    /// `description` Human-readable description of the initialized role
111    /// `msg_sender` The message sender address
112    fn initialize_role_and_grant_to_sender(
113        &mut self,
114        admin_role: Bytes32,
115        description: String,
116        msg_sender: &Self::Address,
117    ) -> Result<Bytes32, Error> {
118        ensure!(!description.is_empty(), Error::RoleDescriptionEmpty)?;
119        let role = self.derive_role(admin_role, description);
120
121        // AccessControl roles have `DEFAULT_ADMIN_ROLE` (i.e., `bytes32(0)`)
122        // as their `admin_role` by default. No account in AccessControlRegistry
123        // can possibly have that role, which means all initialized roles will
124        // have non-default admin roles, and vice versa.
125        if self.get_role_admin(&role) == Some(Self::DEFAULT_ADMIN_ROLE) {
126            if admin_role == self.derive_root_role(msg_sender) {
127                self.initialize_manager(msg_sender)?;
128            }
129            self.set_role_admin(&role, admin_role)?;
130        }
131        self.grant_role(&role, msg_sender)?;
132        Ok(role)
133    }
134    /// Derives the admin role of the manager
135    /// `manager` Manager address
136    fn derive_admin_role(&self, manager: &Self::Address) -> Bytes32 {
137        self.derive_role(
138            self.derive_root_role(manager),
139            self.admin_role_description(),
140        )
141    }
142    /// Derives the root role of the manager
143    /// `manager` Manager address
144    fn derive_root_role(&self, manager: &Self::Address) -> Bytes32 {
145        RoleDeriver::derive_root_role(manager.as_ref())
146    }
147    /// Derives the role using its admin role and description
148    ///
149    /// This implies that roles adminned by the same role cannot have the
150    /// same description
151    /// `admin_role` Admin role
152    /// `description` Human-readable description of the role
153    fn derive_role(&self, admin_role: Bytes32, description: String) -> Bytes32 {
154        RoleDeriver::derive_role(admin_role, description)
155    }
156}
157
158/// Contract that implements the AccessControlRegistry role derivation logic
159///
160/// If a contract interfaces with AccessControlRegistry and needs to
161/// derive roles, it should inherit this contract instead of re-implementing
162/// the logic
163pub struct RoleDeriver;
164
165impl RoleDeriver {
166    /// Derives the root role of the manager
167    /// `manager` Manager address
168    /// `rootRole` Root role
169    pub fn derive_root_role(manager: &[u8]) -> Bytes32 {
170        keccak_packed(&[Token::FixedBytes(manager.to_vec())])
171    }
172
173    /// Derives the role using its admin role and description
174    ///
175    /// This implies that roles adminned by the same role cannot have the
176    /// same description
177    /// `admin_role` Admin role
178    /// `description` Human-readable description of the role
179    pub fn derive_role(admin_role: Bytes32, description: String) -> Bytes32 {
180        Self::derive_role_with_hash(admin_role, keccak_packed(&[Token::String(description)]))
181    }
182
183    /// Derives the role using its admin role and description hash
184    ///
185    /// This implies that roles adminned by the same role cannot have the
186    /// same description
187    /// `admin_role` Admin role
188    /// `description` Hash of the human-readable description of the role
189    pub fn derive_role_with_hash(admin_role: Bytes32, description_hash: Bytes32) -> Bytes32 {
190        keccak_packed(&[
191            Token::FixedBytes(admin_role.to_vec()),
192            Token::FixedBytes(description_hash.to_vec()),
193        ])
194    }
195}
196
197#[cfg(test)]
198mod tests {}