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 {}