/home/runner/work/torus-substrate/torus-substrate/pallets/permission0/src/ext.rs
Line | Count | Source |
1 | | use crate::permission::EnforcementReferendum; |
2 | | use crate::{ |
3 | | Config, EnforcementAuthority, EnforcementTracking, Error, Event, Pallet, PermissionDuration, |
4 | | PermissionId, PermissionScope, Permissions, RevocationTerms, pallet, |
5 | | }; |
6 | | use pallet_permission0_api::{ |
7 | | EnforcementAuthority as ApiEnforcementAuthority, Permission0Api, |
8 | | PermissionDuration as ApiPermissionDuration, RevocationTerms as ApiRevocationTerms, |
9 | | }; |
10 | | use polkadot_sdk::{ |
11 | | frame_support::ensure, |
12 | | frame_system::ensure_signed_or_root, |
13 | | polkadot_sdk_frame::prelude::{BlockNumberFor, OriginFor}, |
14 | | sp_runtime::{DispatchError, DispatchResult}, |
15 | | }; |
16 | | |
17 | | pub mod curator_impl; |
18 | | pub mod namespace_impl; |
19 | | pub mod stream_impl; |
20 | | pub mod wallet_impl; |
21 | | |
22 | | /// Implementation of the Permission0Api trait to be used externally |
23 | | impl<T: Config> Permission0Api<OriginFor<T>> for pallet::Pallet<T> { |
24 | 0 | fn permission_exists(id: &PermissionId) -> bool { |
25 | 0 | Permissions::<T>::contains_key(id) |
26 | 0 | } |
27 | | |
28 | 0 | fn revoke_permission(who: OriginFor<T>, permission_id: &PermissionId) -> DispatchResult { |
29 | 0 | revoke_permission_impl::<T>(who, permission_id) |
30 | 0 | } |
31 | | |
32 | 0 | fn execute_permission(who: OriginFor<T>, permission_id: &PermissionId) -> DispatchResult { |
33 | 0 | execute_permission_impl::<T>(who, permission_id) |
34 | 0 | } |
35 | | } |
36 | | |
37 | 68 | fn translate_duration<T: Config>( |
38 | 68 | duration: ApiPermissionDuration<BlockNumberFor<T>>, |
39 | 68 | ) -> Result<PermissionDuration<T>, DispatchError> { |
40 | 68 | Ok(match duration { |
41 | 2 | ApiPermissionDuration::UntilBlock(block) => { |
42 | 2 | let current_block = <polkadot_sdk::frame_system::Pallet<T>>::block_number(); |
43 | 2 | ensure!(block > current_block, Error::<T>::InvalidInterval0 ); |
44 | | |
45 | 2 | PermissionDuration::UntilBlock(block) |
46 | | } |
47 | 66 | ApiPermissionDuration::Indefinite => PermissionDuration::Indefinite, |
48 | | }) |
49 | 68 | } |
50 | | |
51 | 68 | fn translate_revocation_terms<T: Config>( |
52 | 68 | revocation: ApiRevocationTerms<T::AccountId, BlockNumberFor<T>>, |
53 | 68 | ) -> Result<RevocationTerms<T>, DispatchError> { |
54 | 68 | let revocation62 = match revocation { |
55 | 48 | ApiRevocationTerms::Irrevocable => RevocationTerms::Irrevocable, |
56 | 4 | ApiRevocationTerms::RevocableByDelegator => RevocationTerms::RevocableByDelegator, |
57 | | ApiRevocationTerms::RevocableByArbiters { |
58 | 10 | accounts, |
59 | 10 | required_votes, |
60 | | } => { |
61 | 10 | ensure!(required_votes > 0, Error::<T>::InvalidNumberOfRevokers4 ); |
62 | 6 | ensure!(!accounts.is_empty(), Error::<T>::InvalidNumberOfRevokers0 ); |
63 | | |
64 | 6 | ensure!( |
65 | 6 | required_votes as usize <= accounts.len(), |
66 | 2 | Error::<T>::InvalidNumberOfRevokers |
67 | | ); |
68 | | |
69 | | RevocationTerms::RevocableByArbiters { |
70 | 4 | accounts: accounts |
71 | 4 | .try_into() |
72 | 4 | .map_err(|_| crate::Error::<T>::TooManyRevokers)?0 , |
73 | 4 | required_votes, |
74 | | } |
75 | | } |
76 | 6 | ApiRevocationTerms::RevocableAfter(block) => { |
77 | 6 | let current_block = <polkadot_sdk::frame_system::Pallet<T>>::block_number(); |
78 | 6 | ensure!(block > current_block, Error::<T>::InvalidInterval0 ); |
79 | | |
80 | 6 | RevocationTerms::RevocableAfter(block) |
81 | | } |
82 | | }; |
83 | | |
84 | 62 | Ok(revocation) |
85 | 68 | } |
86 | | |
87 | 62 | fn translate_enforcement_authority<T: Config>( |
88 | 62 | enforcement: ApiEnforcementAuthority<T::AccountId>, |
89 | 62 | ) -> Result<EnforcementAuthority<T>, DispatchError> { |
90 | 62 | let enforcement = match enforcement { |
91 | 50 | ApiEnforcementAuthority::None => EnforcementAuthority::None, |
92 | | ApiEnforcementAuthority::ControlledBy { |
93 | 12 | controllers, |
94 | 12 | required_votes, |
95 | | } => { |
96 | 12 | ensure!(required_votes > 0, Error::<T>::InvalidNumberOfControllers0 ); |
97 | 12 | ensure!( |
98 | 12 | !controllers.is_empty(), |
99 | 0 | Error::<T>::InvalidNumberOfControllers |
100 | | ); |
101 | | |
102 | 12 | ensure!( |
103 | 12 | required_votes as usize <= controllers.len(), |
104 | 0 | Error::<T>::InvalidNumberOfControllers |
105 | | ); |
106 | | |
107 | | EnforcementAuthority::ControlledBy { |
108 | 12 | controllers: controllers |
109 | 12 | .try_into() |
110 | 12 | .map_err(|_| crate::Error::<T>::TooManyControllers)?0 , |
111 | 12 | required_votes, |
112 | | } |
113 | | } |
114 | | }; |
115 | | |
116 | 62 | Ok(enforcement) |
117 | 62 | } |
118 | | |
119 | | /// Revoke a permission implementation |
120 | 40 | pub(crate) fn revoke_permission_impl<T: Config>( |
121 | 40 | origin: OriginFor<T>, |
122 | 40 | permission_id: &PermissionId, |
123 | 40 | ) -> DispatchResult { |
124 | 40 | let contract38 = Permissions::<T>::get(permission_id).ok_or(Error::<T>::PermissionNotFound)?2 ; |
125 | 38 | contract.revoke(origin, *permission_id) |
126 | 40 | } |
127 | | |
128 | | /// Execute a permission implementation |
129 | 16 | pub(crate) fn execute_permission_impl<T: Config>( |
130 | 16 | who: OriginFor<T>, |
131 | 16 | permission_id: &PermissionId, |
132 | 16 | ) -> DispatchResult { |
133 | 16 | let who = ensure_signed_or_root(who)?0 ; |
134 | | |
135 | 16 | let contract14 = Permissions::<T>::get(permission_id).ok_or(Error::<T>::PermissionNotFound)?2 ; |
136 | | |
137 | 14 | let delegator = contract.delegator.clone(); |
138 | | |
139 | 14 | ensure!( |
140 | 14 | who.is_none() || who.as_ref() == Some(&delegator)12 , |
141 | 0 | Error::<T>::NotPermissionDelegator |
142 | | ); |
143 | | |
144 | 14 | match &contract.scope { |
145 | 12 | PermissionScope::Stream(stream_scope) => { |
146 | 12 | stream_impl::execute_permission_impl(permission_id, &contract, stream_scope) |
147 | | } |
148 | 2 | PermissionScope::Curator(_) => curator_impl::execute_permission_impl::<T>(permission_id), |
149 | 0 | PermissionScope::Namespace(_) => Ok(()), |
150 | 0 | PermissionScope::Wallet(_) => Ok(()), |
151 | | } |
152 | 16 | } |
153 | | |
154 | | /// Execute a permission through enforcement authority |
155 | 12 | pub fn enforcement_execute_permission_impl<T: Config>( |
156 | 12 | origin: OriginFor<T>, |
157 | 12 | permission_id: PermissionId, |
158 | 12 | ) -> DispatchResult { |
159 | 12 | let who = ensure_signed_or_root(origin)?0 ; |
160 | | |
161 | 12 | let contract = Permissions::<T>::get(permission_id).ok_or(Error::<T>::PermissionNotFound)?0 ; |
162 | | |
163 | | // If not root, check enforcement authority |
164 | 12 | if let Some(who) = &who { |
165 | 12 | match &contract.enforcement { |
166 | | EnforcementAuthority::None => { |
167 | 0 | return Err(Error::<T>::NotAuthorizedToToggle.into()); |
168 | | } |
169 | | EnforcementAuthority::ControlledBy { |
170 | 12 | controllers, |
171 | 12 | required_votes, |
172 | | } => { |
173 | 12 | ensure!(controllers.contains(who), Error::<T>::NotAuthorizedToToggle2 ); |
174 | | |
175 | 10 | let referendum = EnforcementReferendum::Execution; |
176 | 10 | let votes = EnforcementTracking::<T>::get(permission_id, &referendum) |
177 | 10 | .into_iter() |
178 | 10 | .filter(|id| id4 != who4 ) |
179 | 10 | .filter(|id| controllers2 .contains2 (id2 )) |
180 | 10 | .count(); |
181 | | |
182 | 10 | if votes.saturating_add(1) < *required_votes as usize { |
183 | 4 | return EnforcementTracking::<T>::mutate( |
184 | 4 | permission_id, |
185 | 4 | referendum.clone(), |
186 | 4 | |votes| { |
187 | 4 | votes |
188 | 4 | .try_insert(who.clone()) |
189 | 4 | .map_err(|_| Error::<T>::TooManyControllers)?0 ; |
190 | | |
191 | 4 | <Pallet<T>>::deposit_event(Event::EnforcementVoteCast { |
192 | 4 | permission_id, |
193 | 4 | voter: who.clone(), |
194 | 4 | referendum, |
195 | 4 | }); |
196 | | |
197 | 4 | Ok(()) |
198 | 4 | }, |
199 | | ); |
200 | 6 | } |
201 | | } |
202 | | } |
203 | 0 | } |
204 | | |
205 | 6 | match &contract.scope { |
206 | 6 | PermissionScope::Stream(stream_scope) => { |
207 | 6 | stream_impl::execute_permission_impl(&permission_id, &contract, stream_scope)?2 |
208 | | } |
209 | | PermissionScope::Curator(_) => { |
210 | 0 | return curator_impl::execute_permission_impl::<T>(&permission_id); |
211 | | } |
212 | 0 | PermissionScope::Namespace(_) => return Ok(()), |
213 | 0 | PermissionScope::Wallet(_) => return Ok(()), |
214 | | } |
215 | | |
216 | 4 | EnforcementTracking::<T>::remove(permission_id, EnforcementReferendum::Execution); |
217 | | |
218 | 4 | <Pallet<T>>::deposit_event(Event::PermissionEnforcementExecuted { |
219 | 4 | permission_id, |
220 | 4 | executed_by: who, |
221 | 4 | }); |
222 | | |
223 | 4 | Ok(()) |
224 | 12 | } |