1#![cfg_attr(not(feature = "std"), no_std)]
108
109mod benchmarking;
110pub mod legacy;
111pub mod migration;
112#[cfg(test)]
113mod tests;
114mod types;
115pub mod weights;
116
117extern crate alloc;
118
119use crate::types::{AuthorityProperties, Provider, Suffix, Username, UsernameInformation};
120use alloc::{boxed::Box, vec::Vec};
121use codec::Encode;
122use frame_support::{
123 ensure,
124 pallet_prelude::{DispatchError, DispatchResult},
125 traits::{
126 BalanceStatus, Currency, Defensive, Get, OnUnbalanced, ReservableCurrency, StorageVersion,
127 },
128 BoundedVec,
129};
130use frame_system::pallet_prelude::*;
131pub use pallet::*;
132use sp_runtime::traits::{
133 AppendZerosInput, Hash, IdentifyAccount, Saturating, StaticLookup, Verify, Zero,
134};
135pub use types::{
136 Data, IdentityInformationProvider, Judgement, RegistrarIndex, RegistrarInfo, Registration,
137};
138pub use weights::WeightInfo;
139
140type BalanceOf<T> =
141 <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
142type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
143 <T as frame_system::Config>::AccountId,
144>>::NegativeImbalance;
145type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
146type ProviderOf<T> = Provider<BalanceOf<T>>;
147
148#[frame_support::pallet]
149pub mod pallet {
150 use super::*;
151 use frame_support::pallet_prelude::*;
152
153 #[cfg(feature = "runtime-benchmarks")]
154 pub trait BenchmarkHelper<Public, Signature> {
155 fn sign_message(message: &[u8]) -> (Public, Signature);
156 }
157 #[cfg(feature = "runtime-benchmarks")]
158 impl BenchmarkHelper<sp_runtime::MultiSigner, sp_runtime::MultiSignature> for () {
159 fn sign_message(message: &[u8]) -> (sp_runtime::MultiSigner, sp_runtime::MultiSignature) {
160 let public = sp_io::crypto::sr25519_generate(0.into(), None);
161 let signature = sp_runtime::MultiSignature::Sr25519(
162 sp_io::crypto::sr25519_sign(
163 0.into(),
164 &public.into_account().try_into().unwrap(),
165 message,
166 )
167 .unwrap(),
168 );
169 (public.into(), signature)
170 }
171 }
172
173 #[pallet::config]
174 pub trait Config: frame_system::Config {
175 #[allow(deprecated)]
177 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
178
179 type Currency: ReservableCurrency<Self::AccountId>;
181
182 #[pallet::constant]
184 type BasicDeposit: Get<BalanceOf<Self>>;
185
186 #[pallet::constant]
188 type ByteDeposit: Get<BalanceOf<Self>>;
189
190 #[pallet::constant]
193 type UsernameDeposit: Get<BalanceOf<Self>>;
194
195 #[pallet::constant]
199 type SubAccountDeposit: Get<BalanceOf<Self>>;
200
201 #[pallet::constant]
203 type MaxSubAccounts: Get<u32>;
204
205 type IdentityInformation: IdentityInformationProvider;
207
208 #[pallet::constant]
211 type MaxRegistrars: Get<u32>;
212
213 type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;
215
216 type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
218
219 type RegistrarOrigin: EnsureOrigin<Self::RuntimeOrigin>;
221
222 type OffchainSignature: Verify<Signer = Self::SigningPublicKey> + Parameter;
226
227 type SigningPublicKey: IdentifyAccount<AccountId = Self::AccountId>;
229
230 type UsernameAuthorityOrigin: EnsureOrigin<Self::RuntimeOrigin>;
232
233 #[pallet::constant]
235 type PendingUsernameExpiration: Get<BlockNumberFor<Self>>;
236
237 #[pallet::constant]
240 type UsernameGracePeriod: Get<BlockNumberFor<Self>>;
241
242 #[pallet::constant]
244 type MaxSuffixLength: Get<u32>;
245
246 #[pallet::constant]
248 type MaxUsernameLength: Get<u32>;
249
250 #[cfg(feature = "runtime-benchmarks")]
253 type BenchmarkHelper: BenchmarkHelper<Self::SigningPublicKey, Self::OffchainSignature>;
254
255 type WeightInfo: WeightInfo;
257 }
258
259 const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
260
261 #[pallet::pallet]
262 #[pallet::storage_version(STORAGE_VERSION)]
263 pub struct Pallet<T>(_);
264
265 #[pallet::storage]
270 pub type IdentityOf<T: Config> = StorageMap<
271 _,
272 Twox64Concat,
273 T::AccountId,
274 Registration<BalanceOf<T>, T::MaxRegistrars, T::IdentityInformation>,
275 OptionQuery,
276 >;
277
278 #[pallet::storage]
280 pub type UsernameOf<T: Config> =
281 StorageMap<_, Twox64Concat, T::AccountId, Username<T>, OptionQuery>;
282
283 #[pallet::storage]
286 pub type SuperOf<T: Config> =
287 StorageMap<_, Blake2_128Concat, T::AccountId, (T::AccountId, Data), OptionQuery>;
288
289 #[pallet::storage]
295 pub type SubsOf<T: Config> = StorageMap<
296 _,
297 Twox64Concat,
298 T::AccountId,
299 (BalanceOf<T>, BoundedVec<T::AccountId, T::MaxSubAccounts>),
300 ValueQuery,
301 >;
302
303 #[pallet::storage]
308 pub type Registrars<T: Config> = StorageValue<
309 _,
310 BoundedVec<
311 Option<
312 RegistrarInfo<
313 BalanceOf<T>,
314 T::AccountId,
315 <T::IdentityInformation as IdentityInformationProvider>::FieldsIdentifier,
316 >,
317 >,
318 T::MaxRegistrars,
319 >,
320 ValueQuery,
321 >;
322
323 #[pallet::storage]
325 pub type AuthorityOf<T: Config> =
326 StorageMap<_, Twox64Concat, Suffix<T>, AuthorityProperties<T::AccountId>, OptionQuery>;
327
328 #[pallet::storage]
335 pub type UsernameInfoOf<T: Config> = StorageMap<
336 _,
337 Blake2_128Concat,
338 Username<T>,
339 UsernameInformation<T::AccountId, BalanceOf<T>>,
340 OptionQuery,
341 >;
342
343 #[pallet::storage]
350 pub type PendingUsernames<T: Config> = StorageMap<
351 _,
352 Blake2_128Concat,
353 Username<T>,
354 (T::AccountId, BlockNumberFor<T>, ProviderOf<T>),
355 OptionQuery,
356 >;
357
358 #[pallet::storage]
363 pub type UnbindingUsernames<T: Config> =
364 StorageMap<_, Blake2_128Concat, Username<T>, BlockNumberFor<T>, OptionQuery>;
365
366 #[pallet::error]
367 pub enum Error<T> {
368 TooManySubAccounts,
370 NotFound,
372 NotNamed,
374 EmptyIndex,
376 FeeChanged,
378 NoIdentity,
380 StickyJudgement,
382 JudgementGiven,
384 InvalidJudgement,
386 InvalidIndex,
388 InvalidTarget,
390 TooManyRegistrars,
392 AlreadyClaimed,
394 NotSub,
396 NotOwned,
398 JudgementForDifferentIdentity,
400 JudgementPaymentFailed,
402 InvalidSuffix,
404 NotUsernameAuthority,
406 NoAllocation,
408 InvalidSignature,
410 RequiresSignature,
412 InvalidUsername,
414 UsernameTaken,
416 NoUsername,
418 NotExpired,
420 TooEarly,
422 NotUnbinding,
424 AlreadyUnbinding,
426 InsufficientPrivileges,
429 }
430
431 #[pallet::event]
432 #[pallet::generate_deposit(pub(super) fn deposit_event)]
433 pub enum Event<T: Config> {
434 IdentitySet { who: T::AccountId },
436 IdentityCleared { who: T::AccountId, deposit: BalanceOf<T> },
438 IdentityKilled { who: T::AccountId, deposit: BalanceOf<T> },
440 JudgementRequested { who: T::AccountId, registrar_index: RegistrarIndex },
442 JudgementUnrequested { who: T::AccountId, registrar_index: RegistrarIndex },
444 JudgementGiven { target: T::AccountId, registrar_index: RegistrarIndex },
446 RegistrarAdded { registrar_index: RegistrarIndex },
448 RegistrarRemoved { registrar_index: RegistrarIndex },
450 SubIdentityAdded { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
452 SubIdentitiesSet { main: T::AccountId, number_of_subs: u32, new_deposit: BalanceOf<T> },
454 SubIdentityRenamed { sub: T::AccountId, main: T::AccountId },
456 SubIdentityRemoved { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
458 SubIdentityRevoked { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
461 AuthorityAdded { authority: T::AccountId },
463 AuthorityRemoved { authority: T::AccountId },
465 UsernameSet { who: T::AccountId, username: Username<T> },
467 UsernameQueued { who: T::AccountId, username: Username<T>, expiration: BlockNumberFor<T> },
469 PreapprovalExpired { whose: T::AccountId },
471 PrimaryUsernameSet { who: T::AccountId, username: Username<T> },
473 DanglingUsernameRemoved { who: T::AccountId, username: Username<T> },
476 UsernameUnbound { username: Username<T> },
478 UsernameRemoved { username: Username<T> },
480 UsernameKilled { username: Username<T> },
482 }
483
484 #[pallet::call]
485 impl<T: Config> Pallet<T> {
487 #[pallet::call_index(0)]
495 #[pallet::weight(T::WeightInfo::add_registrar(T::MaxRegistrars::get()))]
496 pub fn add_registrar(
497 origin: OriginFor<T>,
498 account: AccountIdLookupOf<T>,
499 ) -> DispatchResultWithPostInfo {
500 T::RegistrarOrigin::ensure_origin(origin)?;
501 let account = T::Lookup::lookup(account)?;
502
503 let (i, registrar_count) = Registrars::<T>::try_mutate(
504 |registrars| -> Result<(RegistrarIndex, usize), DispatchError> {
505 registrars
506 .try_push(Some(RegistrarInfo {
507 account,
508 fee: Zero::zero(),
509 fields: Default::default(),
510 }))
511 .map_err(|_| Error::<T>::TooManyRegistrars)?;
512 Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len()))
513 },
514 )?;
515
516 Self::deposit_event(Event::RegistrarAdded { registrar_index: i });
517
518 Ok(Some(T::WeightInfo::add_registrar(registrar_count as u32)).into())
519 }
520
521 #[pallet::call_index(24)]
540 #[pallet::weight(T::WeightInfo::remove_registrar(T::MaxRegistrars::get()))]
541 pub fn remove_registrar(
542 origin: OriginFor<T>,
543 #[pallet::compact] index: RegistrarIndex,
544 ) -> DispatchResultWithPostInfo {
545 T::RegistrarOrigin::ensure_origin(origin)?;
546
547 let registrar_count =
548 Registrars::<T>::try_mutate(|registrars| -> Result<usize, DispatchError> {
549 let slot =
550 registrars.get_mut(index as usize).ok_or(Error::<T>::InvalidIndex)?;
551 ensure!(slot.take().is_some(), Error::<T>::EmptyIndex);
552 Ok(registrars.len())
553 })?;
554
555 Self::deposit_event(Event::RegistrarRemoved { registrar_index: index });
556
557 Ok(Some(T::WeightInfo::remove_registrar(registrar_count as u32)).into())
558 }
559
560 #[pallet::call_index(1)]
571 #[pallet::weight(T::WeightInfo::set_identity(T::MaxRegistrars::get()))]
572 pub fn set_identity(
573 origin: OriginFor<T>,
574 info: Box<T::IdentityInformation>,
575 ) -> DispatchResultWithPostInfo {
576 let sender = ensure_signed(origin)?;
577
578 let mut id = match IdentityOf::<T>::get(&sender) {
579 Some(mut id) => {
580 id.judgements.retain(|j| j.1.is_sticky());
582 id.info = *info;
583 id
584 },
585 None => Registration {
586 info: *info,
587 judgements: BoundedVec::default(),
588 deposit: Zero::zero(),
589 },
590 };
591
592 let new_deposit = Self::calculate_identity_deposit(&id.info);
593 let old_deposit = id.deposit;
594 Self::rejig_deposit(&sender, old_deposit, new_deposit)?;
595
596 id.deposit = new_deposit;
597 let judgements = id.judgements.len();
598 IdentityOf::<T>::insert(&sender, id);
599 Self::deposit_event(Event::IdentitySet { who: sender });
600
601 Ok(Some(T::WeightInfo::set_identity(judgements as u32)).into())
602 }
603
604 #[pallet::call_index(2)]
620 #[pallet::weight(T::WeightInfo::set_subs_old(T::MaxSubAccounts::get())
621 .saturating_add(T::WeightInfo::set_subs_new(subs.len() as u32))
622 )]
623 pub fn set_subs(
624 origin: OriginFor<T>,
625 subs: Vec<(T::AccountId, Data)>,
626 ) -> DispatchResultWithPostInfo {
627 let sender = ensure_signed(origin)?;
628 ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NotFound);
629 ensure!(
630 subs.len() <= T::MaxSubAccounts::get() as usize,
631 Error::<T>::TooManySubAccounts
632 );
633
634 let (old_deposit, old_ids) = SubsOf::<T>::get(&sender);
635 let new_deposit = Self::subs_deposit(subs.len() as u32);
636
637 let not_other_sub =
638 subs.iter().filter_map(|i| SuperOf::<T>::get(&i.0)).all(|i| i.0 == sender);
639 ensure!(not_other_sub, Error::<T>::AlreadyClaimed);
640
641 if old_deposit < new_deposit {
642 T::Currency::reserve(&sender, new_deposit - old_deposit)?;
643 } else if old_deposit > new_deposit {
644 let err_amount = T::Currency::unreserve(&sender, old_deposit - new_deposit);
645 debug_assert!(err_amount.is_zero());
646 }
647 for s in old_ids.iter() {
650 SuperOf::<T>::remove(s);
651 }
652 let mut ids = BoundedVec::<T::AccountId, T::MaxSubAccounts>::default();
653 for (id, name) in subs {
654 SuperOf::<T>::insert(&id, (sender.clone(), name));
655 ids.try_push(id).expect("subs length is less than T::MaxSubAccounts; qed");
656 }
657 let new_subs = ids.len();
658
659 if ids.is_empty() {
660 SubsOf::<T>::remove(&sender);
661 } else {
662 SubsOf::<T>::insert(&sender, (new_deposit, ids));
663 }
664
665 Self::deposit_event(Event::SubIdentitiesSet {
666 main: sender,
667 number_of_subs: new_subs as u32,
668 new_deposit,
669 });
670
671 Ok(Some(
672 T::WeightInfo::set_subs_old(old_ids.len() as u32) .saturating_add(T::WeightInfo::set_subs_new(new_subs as u32)),
675 )
676 .into())
677 }
678
679 #[pallet::call_index(3)]
688 #[pallet::weight(T::WeightInfo::clear_identity(
689 T::MaxRegistrars::get(),
690 T::MaxSubAccounts::get(),
691 ))]
692 pub fn clear_identity(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
693 let sender = ensure_signed(origin)?;
694
695 let (subs_deposit, sub_ids) = SubsOf::<T>::take(&sender);
696 let id = IdentityOf::<T>::take(&sender).ok_or(Error::<T>::NoIdentity)?;
697 let deposit = id.total_deposit().saturating_add(subs_deposit);
698 for sub in sub_ids.iter() {
699 SuperOf::<T>::remove(sub);
700 }
701
702 let err_amount = T::Currency::unreserve(&sender, deposit);
703 debug_assert!(err_amount.is_zero());
704
705 Self::deposit_event(Event::IdentityCleared { who: sender, deposit });
706
707 #[allow(deprecated)]
708 Ok(Some(T::WeightInfo::clear_identity(
709 id.judgements.len() as u32,
710 sub_ids.len() as u32,
711 ))
712 .into())
713 }
714
715 #[pallet::call_index(4)]
732 #[pallet::weight(T::WeightInfo::request_judgement(T::MaxRegistrars::get(),))]
733 pub fn request_judgement(
734 origin: OriginFor<T>,
735 #[pallet::compact] reg_index: RegistrarIndex,
736 #[pallet::compact] max_fee: BalanceOf<T>,
737 ) -> DispatchResultWithPostInfo {
738 let sender = ensure_signed(origin)?;
739 let registrars = Registrars::<T>::get();
740 let registrar = registrars
741 .get(reg_index as usize)
742 .and_then(Option::as_ref)
743 .ok_or(Error::<T>::EmptyIndex)?;
744 ensure!(max_fee >= registrar.fee, Error::<T>::FeeChanged);
745 let mut id = IdentityOf::<T>::get(&sender).ok_or(Error::<T>::NoIdentity)?;
746
747 let item = (reg_index, Judgement::FeePaid(registrar.fee));
748 match id.judgements.binary_search_by_key(®_index, |x| x.0) {
749 Ok(i) => {
750 if id.judgements[i].1.is_sticky() {
751 return Err(Error::<T>::StickyJudgement.into());
752 } else {
753 id.judgements[i] = item
754 }
755 },
756 Err(i) => {
757 id.judgements.try_insert(i, item).map_err(|_| Error::<T>::TooManyRegistrars)?
758 },
759 }
760
761 T::Currency::reserve(&sender, registrar.fee)?;
762
763 let judgements = id.judgements.len();
764 IdentityOf::<T>::insert(&sender, id);
765
766 Self::deposit_event(Event::JudgementRequested {
767 who: sender,
768 registrar_index: reg_index,
769 });
770
771 Ok(Some(T::WeightInfo::request_judgement(judgements as u32)).into())
772 }
773
774 #[pallet::call_index(5)]
785 #[pallet::weight(T::WeightInfo::cancel_request(T::MaxRegistrars::get()))]
786 pub fn cancel_request(
787 origin: OriginFor<T>,
788 reg_index: RegistrarIndex,
789 ) -> DispatchResultWithPostInfo {
790 let sender = ensure_signed(origin)?;
791 let mut id = IdentityOf::<T>::get(&sender).ok_or(Error::<T>::NoIdentity)?;
792
793 let pos = id
794 .judgements
795 .binary_search_by_key(®_index, |x| x.0)
796 .map_err(|_| Error::<T>::NotFound)?;
797 let fee = if let Judgement::FeePaid(fee) = id.judgements.remove(pos).1 {
798 fee
799 } else {
800 return Err(Error::<T>::JudgementGiven.into());
801 };
802
803 let err_amount = T::Currency::unreserve(&sender, fee);
804 debug_assert!(err_amount.is_zero());
805 let judgements = id.judgements.len();
806 IdentityOf::<T>::insert(&sender, id);
807
808 Self::deposit_event(Event::JudgementUnrequested {
809 who: sender,
810 registrar_index: reg_index,
811 });
812
813 Ok(Some(T::WeightInfo::cancel_request(judgements as u32)).into())
814 }
815
816 #[pallet::call_index(6)]
824 #[pallet::weight(T::WeightInfo::set_fee(T::MaxRegistrars::get()))]
825 pub fn set_fee(
826 origin: OriginFor<T>,
827 #[pallet::compact] index: RegistrarIndex,
828 #[pallet::compact] fee: BalanceOf<T>,
829 ) -> DispatchResultWithPostInfo {
830 let who = ensure_signed(origin)?;
831
832 let registrars = Registrars::<T>::mutate(|rs| -> Result<usize, DispatchError> {
833 rs.get_mut(index as usize)
834 .and_then(|x| x.as_mut())
835 .and_then(|r| {
836 if r.account == who {
837 r.fee = fee;
838 Some(())
839 } else {
840 None
841 }
842 })
843 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
844 Ok(rs.len())
845 })?;
846 Ok(Some(T::WeightInfo::set_fee(registrars as u32)).into())
847 }
848
849 #[pallet::call_index(7)]
857 #[pallet::weight(T::WeightInfo::set_account_id(T::MaxRegistrars::get()))]
858 pub fn set_account_id(
859 origin: OriginFor<T>,
860 #[pallet::compact] index: RegistrarIndex,
861 new: AccountIdLookupOf<T>,
862 ) -> DispatchResultWithPostInfo {
863 let who = ensure_signed(origin)?;
864 let new = T::Lookup::lookup(new)?;
865
866 let registrars = Registrars::<T>::mutate(|rs| -> Result<usize, DispatchError> {
867 rs.get_mut(index as usize)
868 .and_then(|x| x.as_mut())
869 .and_then(|r| {
870 if r.account == who {
871 r.account = new;
872 Some(())
873 } else {
874 None
875 }
876 })
877 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
878 Ok(rs.len())
879 })?;
880 Ok(Some(T::WeightInfo::set_account_id(registrars as u32)).into())
881 }
882
883 #[pallet::call_index(8)]
891 #[pallet::weight(T::WeightInfo::set_fields(T::MaxRegistrars::get()))]
892 pub fn set_fields(
893 origin: OriginFor<T>,
894 #[pallet::compact] index: RegistrarIndex,
895 fields: <T::IdentityInformation as IdentityInformationProvider>::FieldsIdentifier,
896 ) -> DispatchResultWithPostInfo {
897 let who = ensure_signed(origin)?;
898
899 let registrars =
900 Registrars::<T>::mutate(|registrars| -> Result<usize, DispatchError> {
901 let registrar = registrars
902 .get_mut(index as usize)
903 .and_then(|r| r.as_mut())
904 .filter(|r| r.account == who)
905 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
906 registrar.fields = fields;
907
908 Ok(registrars.len())
909 })?;
910 Ok(Some(T::WeightInfo::set_fields(registrars as u32)).into())
911 }
912
913 #[pallet::call_index(9)]
929 #[pallet::weight(T::WeightInfo::provide_judgement(T::MaxRegistrars::get()))]
930 pub fn provide_judgement(
931 origin: OriginFor<T>,
932 #[pallet::compact] reg_index: RegistrarIndex,
933 target: AccountIdLookupOf<T>,
934 judgement: Judgement<BalanceOf<T>>,
935 identity: T::Hash,
936 ) -> DispatchResultWithPostInfo {
937 let sender = ensure_signed(origin)?;
938 let target = T::Lookup::lookup(target)?;
939 ensure!(!judgement.has_deposit(), Error::<T>::InvalidJudgement);
940 Registrars::<T>::get()
941 .get(reg_index as usize)
942 .and_then(Option::as_ref)
943 .filter(|r| r.account == sender)
944 .ok_or(Error::<T>::InvalidIndex)?;
945 let mut id = IdentityOf::<T>::get(&target).ok_or(Error::<T>::InvalidTarget)?;
946
947 if T::Hashing::hash_of(&id.info) != identity {
948 return Err(Error::<T>::JudgementForDifferentIdentity.into());
949 }
950
951 let item = (reg_index, judgement);
952 match id.judgements.binary_search_by_key(®_index, |x| x.0) {
953 Ok(position) => {
954 if let Judgement::FeePaid(fee) = id.judgements[position].1 {
955 T::Currency::repatriate_reserved(
956 &target,
957 &sender,
958 fee,
959 BalanceStatus::Free,
960 )
961 .map_err(|_| Error::<T>::JudgementPaymentFailed)?;
962 }
963 id.judgements[position] = item
964 },
965 Err(position) => id
966 .judgements
967 .try_insert(position, item)
968 .map_err(|_| Error::<T>::TooManyRegistrars)?,
969 }
970
971 let judgements = id.judgements.len();
972 IdentityOf::<T>::insert(&target, id);
973 Self::deposit_event(Event::JudgementGiven { target, registrar_index: reg_index });
974
975 Ok(Some(T::WeightInfo::provide_judgement(judgements as u32)).into())
976 }
977
978 #[pallet::call_index(10)]
991 #[pallet::weight(T::WeightInfo::kill_identity(
992 T::MaxRegistrars::get(),
993 T::MaxSubAccounts::get(),
994 ))]
995 pub fn kill_identity(
996 origin: OriginFor<T>,
997 target: AccountIdLookupOf<T>,
998 ) -> DispatchResultWithPostInfo {
999 T::ForceOrigin::ensure_origin(origin)?;
1000
1001 let target = T::Lookup::lookup(target)?;
1003 let (subs_deposit, sub_ids) = SubsOf::<T>::take(&target);
1005 let id = IdentityOf::<T>::take(&target).ok_or(Error::<T>::NoIdentity)?;
1006 let deposit = id.total_deposit().saturating_add(subs_deposit);
1007 for sub in sub_ids.iter() {
1008 SuperOf::<T>::remove(sub);
1009 }
1010 T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0);
1012
1013 Self::deposit_event(Event::IdentityKilled { who: target, deposit });
1014
1015 #[allow(deprecated)]
1016 Ok(Some(T::WeightInfo::kill_identity(id.judgements.len() as u32, sub_ids.len() as u32))
1017 .into())
1018 }
1019
1020 #[pallet::call_index(11)]
1028 #[pallet::weight(T::WeightInfo::add_sub(T::MaxSubAccounts::get()))]
1029 pub fn add_sub(
1030 origin: OriginFor<T>,
1031 sub: AccountIdLookupOf<T>,
1032 data: Data,
1033 ) -> DispatchResult {
1034 let sender = ensure_signed(origin)?;
1035 let sub = T::Lookup::lookup(sub)?;
1036 ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
1037
1038 ensure!(!SuperOf::<T>::contains_key(&sub), Error::<T>::AlreadyClaimed);
1040
1041 SubsOf::<T>::try_mutate(&sender, |(ref mut subs_deposit, ref mut sub_ids)| {
1042 ensure!(
1044 sub_ids.len() < T::MaxSubAccounts::get() as usize,
1045 Error::<T>::TooManySubAccounts
1046 );
1047 let deposit = T::SubAccountDeposit::get();
1048 T::Currency::reserve(&sender, deposit)?;
1049
1050 SuperOf::<T>::insert(&sub, (sender.clone(), data));
1051 sub_ids.try_push(sub.clone()).expect("sub ids length checked above; qed");
1052 *subs_deposit = subs_deposit.saturating_add(deposit);
1053
1054 Self::deposit_event(Event::SubIdentityAdded { sub, main: sender.clone(), deposit });
1055 Ok(())
1056 })
1057 }
1058
1059 #[pallet::call_index(12)]
1064 #[pallet::weight(T::WeightInfo::rename_sub(T::MaxSubAccounts::get()))]
1065 pub fn rename_sub(
1066 origin: OriginFor<T>,
1067 sub: AccountIdLookupOf<T>,
1068 data: Data,
1069 ) -> DispatchResult {
1070 let sender = ensure_signed(origin)?;
1071 let sub = T::Lookup::lookup(sub)?;
1072 ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
1073 ensure!(SuperOf::<T>::get(&sub).map_or(false, |x| x.0 == sender), Error::<T>::NotOwned);
1074 SuperOf::<T>::insert(&sub, (&sender, data));
1075
1076 Self::deposit_event(Event::SubIdentityRenamed { main: sender, sub });
1077 Ok(())
1078 }
1079
1080 #[pallet::call_index(13)]
1088 #[pallet::weight(T::WeightInfo::remove_sub(T::MaxSubAccounts::get()))]
1089 pub fn remove_sub(origin: OriginFor<T>, sub: AccountIdLookupOf<T>) -> DispatchResult {
1090 let sender = ensure_signed(origin)?;
1091 ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
1092 let sub = T::Lookup::lookup(sub)?;
1093 let (sup, _) = SuperOf::<T>::get(&sub).ok_or(Error::<T>::NotSub)?;
1094 ensure!(sup == sender, Error::<T>::NotOwned);
1095 SuperOf::<T>::remove(&sub);
1096 SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {
1097 sub_ids.retain(|x| x != &sub);
1098 let deposit = T::SubAccountDeposit::get().min(*subs_deposit);
1099 *subs_deposit -= deposit;
1100 let err_amount = T::Currency::unreserve(&sender, deposit);
1101 debug_assert!(err_amount.is_zero());
1102 Self::deposit_event(Event::SubIdentityRemoved { sub, main: sender, deposit });
1103 });
1104 Ok(())
1105 }
1106
1107 #[pallet::call_index(14)]
1118 #[pallet::weight(T::WeightInfo::quit_sub(T::MaxSubAccounts::get()))]
1119 pub fn quit_sub(origin: OriginFor<T>) -> DispatchResult {
1120 let sender = ensure_signed(origin)?;
1121 let (sup, _) = SuperOf::<T>::take(&sender).ok_or(Error::<T>::NotSub)?;
1122 SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {
1123 sub_ids.retain(|x| x != &sender);
1124 let deposit = T::SubAccountDeposit::get().min(*subs_deposit);
1125 *subs_deposit -= deposit;
1126 let _ =
1127 T::Currency::repatriate_reserved(&sup, &sender, deposit, BalanceStatus::Free);
1128 Self::deposit_event(Event::SubIdentityRevoked {
1129 sub: sender,
1130 main: sup.clone(),
1131 deposit,
1132 });
1133 });
1134 Ok(())
1135 }
1136
1137 #[pallet::call_index(15)]
1143 #[pallet::weight(T::WeightInfo::add_username_authority())]
1144 pub fn add_username_authority(
1145 origin: OriginFor<T>,
1146 authority: AccountIdLookupOf<T>,
1147 suffix: Vec<u8>,
1148 allocation: u32,
1149 ) -> DispatchResult {
1150 T::UsernameAuthorityOrigin::ensure_origin(origin)?;
1151 let authority = T::Lookup::lookup(authority)?;
1152 Self::validate_suffix(&suffix)?;
1155 let suffix = Suffix::<T>::try_from(suffix).map_err(|_| Error::<T>::InvalidSuffix)?;
1156 AuthorityOf::<T>::insert(
1158 &suffix,
1159 AuthorityProperties::<T::AccountId> { account_id: authority.clone(), allocation },
1160 );
1161 Self::deposit_event(Event::AuthorityAdded { authority });
1162 Ok(())
1163 }
1164
1165 #[pallet::call_index(16)]
1167 #[pallet::weight(T::WeightInfo::remove_username_authority())]
1168 pub fn remove_username_authority(
1169 origin: OriginFor<T>,
1170 suffix: Vec<u8>,
1171 authority: AccountIdLookupOf<T>,
1172 ) -> DispatchResult {
1173 T::UsernameAuthorityOrigin::ensure_origin(origin)?;
1174 let suffix = Suffix::<T>::try_from(suffix).map_err(|_| Error::<T>::InvalidSuffix)?;
1175 let authority = T::Lookup::lookup(authority)?;
1176 let properties =
1177 AuthorityOf::<T>::take(&suffix).ok_or(Error::<T>::NotUsernameAuthority)?;
1178 ensure!(properties.account_id == authority, Error::<T>::InvalidSuffix);
1179 Self::deposit_event(Event::AuthorityRemoved { authority });
1180 Ok(())
1181 }
1182
1183 #[pallet::call_index(17)]
1197 #[pallet::weight(T::WeightInfo::set_username_for(if *use_allocation { 1 } else { 0 }))]
1198 pub fn set_username_for(
1199 origin: OriginFor<T>,
1200 who: AccountIdLookupOf<T>,
1201 username: Vec<u8>,
1202 signature: Option<T::OffchainSignature>,
1203 use_allocation: bool,
1204 ) -> DispatchResult {
1205 let sender = ensure_signed(origin)?;
1208 let suffix = Self::validate_username(&username)?;
1209 let provider = AuthorityOf::<T>::try_mutate(
1210 &suffix,
1211 |maybe_authority| -> Result<ProviderOf<T>, DispatchError> {
1212 let properties =
1213 maybe_authority.as_mut().ok_or(Error::<T>::NotUsernameAuthority)?;
1214 ensure!(properties.account_id == sender, Error::<T>::NotUsernameAuthority);
1215 if use_allocation {
1216 ensure!(properties.allocation > 0, Error::<T>::NoAllocation);
1217 properties.allocation.saturating_dec();
1218 Ok(Provider::new_with_allocation())
1219 } else {
1220 let deposit = T::UsernameDeposit::get();
1221 T::Currency::reserve(&sender, deposit)?;
1222 Ok(Provider::new_with_deposit(deposit))
1223 }
1224 },
1225 )?;
1226
1227 let bounded_username =
1228 Username::<T>::try_from(username).map_err(|_| Error::<T>::InvalidUsername)?;
1229
1230 ensure!(
1232 !UsernameInfoOf::<T>::contains_key(&bounded_username),
1233 Error::<T>::UsernameTaken
1234 );
1235 ensure!(
1236 !PendingUsernames::<T>::contains_key(&bounded_username),
1237 Error::<T>::UsernameTaken
1238 );
1239
1240 let who = T::Lookup::lookup(who)?;
1242 if let Some(s) = signature {
1243 Self::validate_signature(&bounded_username[..], &s, &who)?;
1246 Self::insert_username(&who, bounded_username, provider);
1247 } else {
1248 Self::queue_acceptance(&who, bounded_username, provider);
1250 }
1251 Ok(())
1252 }
1253
1254 #[pallet::call_index(18)]
1257 #[pallet::weight(T::WeightInfo::accept_username())]
1258 pub fn accept_username(
1259 origin: OriginFor<T>,
1260 username: Username<T>,
1261 ) -> DispatchResultWithPostInfo {
1262 let who = ensure_signed(origin)?;
1263 let (approved_for, _, provider) =
1264 PendingUsernames::<T>::take(&username).ok_or(Error::<T>::NoUsername)?;
1265 ensure!(approved_for == who.clone(), Error::<T>::InvalidUsername);
1266 Self::insert_username(&who, username.clone(), provider);
1267 Self::deposit_event(Event::UsernameSet { who: who.clone(), username });
1268 Ok(Pays::No.into())
1269 }
1270
1271 #[pallet::call_index(19)]
1275 #[pallet::weight(T::WeightInfo::remove_expired_approval(0))]
1276 pub fn remove_expired_approval(
1277 origin: OriginFor<T>,
1278 username: Username<T>,
1279 ) -> DispatchResultWithPostInfo {
1280 ensure_signed(origin)?;
1281 if let Some((who, expiration, provider)) = PendingUsernames::<T>::take(&username) {
1282 let now = frame_system::Pallet::<T>::block_number();
1283 ensure!(now > expiration, Error::<T>::NotExpired);
1284 let actual_weight = match provider {
1285 Provider::AuthorityDeposit(deposit) => {
1286 let suffix = Self::suffix_of_username(&username)
1287 .ok_or(Error::<T>::InvalidUsername)?;
1288 let authority_account = AuthorityOf::<T>::get(&suffix)
1289 .map(|auth_info| auth_info.account_id)
1290 .ok_or(Error::<T>::NotUsernameAuthority)?;
1291 let err_amount = T::Currency::unreserve(&authority_account, deposit);
1292 debug_assert!(err_amount.is_zero());
1293 T::WeightInfo::remove_expired_approval(0)
1294 },
1295 Provider::Allocation => {
1296 T::WeightInfo::remove_expired_approval(1)
1298 },
1299 Provider::System => {
1300 return Err(Error::<T>::InvalidTarget.into());
1302 },
1303 };
1304 Self::deposit_event(Event::PreapprovalExpired { whose: who.clone() });
1305 Ok((Some(actual_weight), Pays::No).into())
1306 } else {
1307 Err(Error::<T>::NoUsername.into())
1308 }
1309 }
1310
1311 #[pallet::call_index(20)]
1313 #[pallet::weight(T::WeightInfo::set_primary_username())]
1314 pub fn set_primary_username(origin: OriginFor<T>, username: Username<T>) -> DispatchResult {
1315 let who = ensure_signed(origin)?;
1317 let account_of_username =
1318 UsernameInfoOf::<T>::get(&username).ok_or(Error::<T>::NoUsername)?.owner;
1319 ensure!(who == account_of_username, Error::<T>::InvalidUsername);
1320 UsernameOf::<T>::insert(&who, username.clone());
1321 Self::deposit_event(Event::PrimaryUsernameSet { who: who.clone(), username });
1322 Ok(())
1323 }
1324
1325 #[pallet::call_index(21)]
1329 #[pallet::weight(T::WeightInfo::unbind_username())]
1330 pub fn unbind_username(origin: OriginFor<T>, username: Username<T>) -> DispatchResult {
1331 let who = ensure_signed(origin)?;
1332 let username_info =
1333 UsernameInfoOf::<T>::get(&username).ok_or(Error::<T>::NoUsername)?;
1334 let suffix = Self::suffix_of_username(&username).ok_or(Error::<T>::InvalidUsername)?;
1335 let authority_account = AuthorityOf::<T>::get(&suffix)
1336 .map(|auth_info| auth_info.account_id)
1337 .ok_or(Error::<T>::NotUsernameAuthority)?;
1338 ensure!(who == authority_account, Error::<T>::NotUsernameAuthority);
1339 match username_info.provider {
1340 Provider::AuthorityDeposit(_) | Provider::Allocation => {
1341 let now = frame_system::Pallet::<T>::block_number();
1342 let grace_period_expiry = now.saturating_add(T::UsernameGracePeriod::get());
1343 UnbindingUsernames::<T>::try_mutate(&username, |maybe_init| {
1344 if maybe_init.is_some() {
1345 return Err(Error::<T>::AlreadyUnbinding);
1346 }
1347 *maybe_init = Some(grace_period_expiry);
1348 Ok(())
1349 })?;
1350 },
1351 Provider::System => return Err(Error::<T>::InsufficientPrivileges.into()),
1352 }
1353 Self::deposit_event(Event::UsernameUnbound { username });
1354 Ok(())
1355 }
1356
1357 #[pallet::call_index(22)]
1360 #[pallet::weight(T::WeightInfo::remove_username())]
1361 pub fn remove_username(
1362 origin: OriginFor<T>,
1363 username: Username<T>,
1364 ) -> DispatchResultWithPostInfo {
1365 ensure_signed(origin)?;
1366 let grace_period_expiry =
1367 UnbindingUsernames::<T>::take(&username).ok_or(Error::<T>::NotUnbinding)?;
1368 let now = frame_system::Pallet::<T>::block_number();
1369 ensure!(now >= grace_period_expiry, Error::<T>::TooEarly);
1370 let username_info = UsernameInfoOf::<T>::take(&username)
1371 .defensive_proof("an unbinding username must exist")
1372 .ok_or(Error::<T>::NoUsername)?;
1373 UsernameOf::<T>::mutate(&username_info.owner, |maybe_primary| {
1375 if maybe_primary.as_ref().map_or(false, |primary| *primary == username) {
1376 *maybe_primary = None;
1377 }
1378 });
1379 match username_info.provider {
1380 Provider::AuthorityDeposit(username_deposit) => {
1381 let suffix = Self::suffix_of_username(&username)
1382 .defensive_proof("registered username must be valid")
1383 .ok_or(Error::<T>::InvalidUsername)?;
1384 if let Some(authority_account) =
1385 AuthorityOf::<T>::get(&suffix).map(|auth_info| auth_info.account_id)
1386 {
1387 let err_amount =
1388 T::Currency::unreserve(&authority_account, username_deposit);
1389 debug_assert!(err_amount.is_zero());
1390 }
1391 },
1392 Provider::Allocation => {
1393 },
1395 Provider::System => return Err(Error::<T>::InsufficientPrivileges.into()),
1396 }
1397 Self::deposit_event(Event::UsernameRemoved { username });
1398 Ok(Pays::No.into())
1399 }
1400
1401 #[pallet::call_index(23)]
1404 #[pallet::weight(T::WeightInfo::kill_username(0))]
1405 pub fn kill_username(
1406 origin: OriginFor<T>,
1407 username: Username<T>,
1408 ) -> DispatchResultWithPostInfo {
1409 T::ForceOrigin::ensure_origin(origin)?;
1410 let username_info =
1411 UsernameInfoOf::<T>::take(&username).ok_or(Error::<T>::NoUsername)?;
1412 UsernameOf::<T>::mutate(&username_info.owner, |maybe_primary| {
1414 if match maybe_primary {
1415 Some(primary) if *primary == username => true,
1416 _ => false,
1417 } {
1418 *maybe_primary = None;
1419 }
1420 });
1421 let _ = UnbindingUsernames::<T>::take(&username);
1422 let actual_weight = match username_info.provider {
1423 Provider::AuthorityDeposit(username_deposit) => {
1424 let suffix =
1425 Self::suffix_of_username(&username).ok_or(Error::<T>::InvalidUsername)?;
1426 if let Some(authority_account) =
1427 AuthorityOf::<T>::get(&suffix).map(|auth_info| auth_info.account_id)
1428 {
1429 T::Slashed::on_unbalanced(
1430 T::Currency::slash_reserved(&authority_account, username_deposit).0,
1431 );
1432 }
1433 T::WeightInfo::kill_username(0)
1434 },
1435 Provider::Allocation => {
1436 T::WeightInfo::kill_username(1)
1438 },
1439 Provider::System => {
1440 T::WeightInfo::kill_username(1)
1442 },
1443 };
1444 Self::deposit_event(Event::UsernameKilled { username });
1445 Ok((Some(actual_weight), Pays::No).into())
1446 }
1447 }
1448}
1449
1450impl<T: Config> Pallet<T> {
1451 pub fn subs(who: &T::AccountId) -> Vec<(T::AccountId, Data)> {
1453 SubsOf::<T>::get(who)
1454 .1
1455 .into_iter()
1456 .filter_map(|a| SuperOf::<T>::get(&a).map(|x| (a, x.1)))
1457 .collect()
1458 }
1459
1460 fn subs_deposit(subs: u32) -> BalanceOf<T> {
1462 T::SubAccountDeposit::get().saturating_mul(BalanceOf::<T>::from(subs))
1463 }
1464
1465 fn rejig_deposit(
1467 who: &T::AccountId,
1468 current: BalanceOf<T>,
1469 new: BalanceOf<T>,
1470 ) -> DispatchResult {
1471 if new > current {
1472 T::Currency::reserve(who, new - current)?;
1473 } else if new < current {
1474 let err_amount = T::Currency::unreserve(who, current - new);
1475 debug_assert!(err_amount.is_zero());
1476 }
1477 Ok(())
1478 }
1479
1480 pub fn has_identity(
1482 who: &T::AccountId,
1483 fields: <T::IdentityInformation as IdentityInformationProvider>::FieldsIdentifier,
1484 ) -> bool {
1485 IdentityOf::<T>::get(who)
1486 .map_or(false, |registration| registration.info.has_identity(fields))
1487 }
1488
1489 fn calculate_identity_deposit(info: &T::IdentityInformation) -> BalanceOf<T> {
1491 let bytes = info.encoded_size() as u32;
1492 let byte_deposit = T::ByteDeposit::get().saturating_mul(BalanceOf::<T>::from(bytes));
1493 T::BasicDeposit::get().saturating_add(byte_deposit)
1494 }
1495
1496 fn validate_username(username: &Vec<u8>) -> Result<Suffix<T>, DispatchError> {
1502 ensure!(
1504 username.len() <= T::MaxUsernameLength::get() as usize,
1505 Error::<T>::InvalidUsername
1506 );
1507
1508 ensure!(!username.is_empty(), Error::<T>::InvalidUsername);
1510 let separator_idx =
1511 username.iter().rposition(|c| *c == b'.').ok_or(Error::<T>::InvalidUsername)?;
1512 ensure!(separator_idx > 0, Error::<T>::InvalidUsername);
1513 let suffix_start = separator_idx.checked_add(1).ok_or(Error::<T>::InvalidUsername)?;
1514 ensure!(suffix_start < username.len(), Error::<T>::InvalidUsername);
1515 ensure!(
1517 username
1518 .iter()
1519 .take(separator_idx)
1520 .all(|byte| byte.is_ascii_digit() || byte.is_ascii_lowercase()),
1521 Error::<T>::InvalidUsername
1522 );
1523 let suffix: Suffix<T> = (&username[suffix_start..])
1524 .to_vec()
1525 .try_into()
1526 .map_err(|_| Error::<T>::InvalidUsername)?;
1527 Ok(suffix)
1528 }
1529
1530 fn suffix_of_username(username: &Username<T>) -> Option<Suffix<T>> {
1532 let separator_idx = username.iter().rposition(|c| *c == b'.')?;
1533 let suffix_start = separator_idx.checked_add(1)?;
1534 if suffix_start >= username.len() {
1535 return None;
1536 }
1537 (&username[suffix_start..]).to_vec().try_into().ok()
1538 }
1539
1540 fn validate_suffix(suffix: &Vec<u8>) -> Result<(), DispatchError> {
1542 ensure!(suffix.len() <= T::MaxSuffixLength::get() as usize, Error::<T>::InvalidSuffix);
1543 ensure!(!suffix.is_empty(), Error::<T>::InvalidSuffix);
1544 ensure!(
1545 suffix.iter().all(|byte| byte.is_ascii_digit() || byte.is_ascii_lowercase()),
1546 Error::<T>::InvalidSuffix
1547 );
1548 Ok(())
1549 }
1550
1551 pub fn validate_signature(
1553 data: &[u8],
1554 signature: &T::OffchainSignature,
1555 signer: &T::AccountId,
1556 ) -> DispatchResult {
1557 if signature.verify(data, &signer) {
1559 return Ok(());
1560 }
1561 let prefix = b"<Bytes>";
1564 let suffix = b"</Bytes>";
1565 let mut wrapped: Vec<u8> = Vec::with_capacity(data.len() + prefix.len() + suffix.len());
1566 wrapped.extend(prefix);
1567 wrapped.extend(data);
1568 wrapped.extend(suffix);
1569
1570 ensure!(signature.verify(&wrapped[..], &signer), Error::<T>::InvalidSignature);
1571
1572 Ok(())
1573 }
1574
1575 pub fn insert_username(who: &T::AccountId, username: Username<T>, provider: ProviderOf<T>) {
1577 let (primary_username, new_is_primary) = match UsernameOf::<T>::get(&who) {
1580 Some(primary) => (primary, false),
1582 None => (username.clone(), true),
1584 };
1585
1586 if new_is_primary {
1587 UsernameOf::<T>::insert(&who, primary_username);
1588 }
1589 let username_info = UsernameInformation { owner: who.clone(), provider };
1590 UsernameInfoOf::<T>::insert(username.clone(), username_info);
1592 Self::deposit_event(Event::UsernameSet { who: who.clone(), username: username.clone() });
1593 if new_is_primary {
1594 Self::deposit_event(Event::PrimaryUsernameSet { who: who.clone(), username });
1595 }
1596 }
1597
1598 pub fn queue_acceptance(who: &T::AccountId, username: Username<T>, provider: ProviderOf<T>) {
1601 let now = frame_system::Pallet::<T>::block_number();
1602 let expiration = now.saturating_add(T::PendingUsernameExpiration::get());
1603 PendingUsernames::<T>::insert(&username, (who.clone(), expiration, provider));
1604 Self::deposit_event(Event::UsernameQueued { who: who.clone(), username, expiration });
1605 }
1606
1607 pub fn reap_identity(who: &T::AccountId) -> Result<(u32, u32, u32), DispatchError> {
1620 let id = IdentityOf::<T>::take(&who).ok_or(Error::<T>::NoIdentity)?;
1623 let registrars = id.judgements.len() as u32;
1624 let encoded_byte_size = id.info.encoded_size() as u32;
1625
1626 let (subs_deposit, sub_ids) = SubsOf::<T>::take(&who);
1628 let actual_subs = sub_ids.len() as u32;
1629 for sub in sub_ids.iter() {
1630 SuperOf::<T>::remove(sub);
1631 }
1632
1633 let deposit = id.total_deposit().saturating_add(subs_deposit);
1635 let err_amount = T::Currency::unreserve(&who, deposit);
1636 debug_assert!(err_amount.is_zero());
1637 Ok((registrars, encoded_byte_size, actual_subs))
1638 }
1639
1640 pub fn poke_deposit(
1650 target: &T::AccountId,
1651 ) -> Result<(BalanceOf<T>, BalanceOf<T>), DispatchError> {
1652 let new_id_deposit = IdentityOf::<T>::try_mutate(
1654 &target,
1655 |identity_of| -> Result<BalanceOf<T>, DispatchError> {
1656 let reg = identity_of.as_mut().ok_or(Error::<T>::NoIdentity)?;
1657 let encoded_byte_size = reg.info.encoded_size() as u32;
1659 let byte_deposit =
1660 T::ByteDeposit::get().saturating_mul(BalanceOf::<T>::from(encoded_byte_size));
1661 let new_id_deposit = T::BasicDeposit::get().saturating_add(byte_deposit);
1662
1663 Self::rejig_deposit(&target, reg.deposit, new_id_deposit)?;
1665
1666 reg.deposit = new_id_deposit;
1667 Ok(new_id_deposit)
1668 },
1669 )?;
1670
1671 let new_subs_deposit = if SubsOf::<T>::contains_key(&target) {
1672 SubsOf::<T>::try_mutate(
1673 &target,
1674 |(current_subs_deposit, subs_of)| -> Result<BalanceOf<T>, DispatchError> {
1675 let new_subs_deposit = Self::subs_deposit(subs_of.len() as u32);
1676 Self::rejig_deposit(&target, *current_subs_deposit, new_subs_deposit)?;
1677 *current_subs_deposit = new_subs_deposit;
1678 Ok(new_subs_deposit)
1679 },
1680 )?
1681 } else {
1682 Zero::zero()
1685 };
1686 Ok((new_id_deposit, new_subs_deposit))
1687 }
1688
1689 #[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
1692 pub fn set_identity_no_deposit(
1693 who: &T::AccountId,
1694 info: T::IdentityInformation,
1695 ) -> DispatchResult {
1696 IdentityOf::<T>::insert(
1697 &who,
1698 Registration {
1699 judgements: Default::default(),
1700 deposit: Zero::zero(),
1701 info: info.clone(),
1702 },
1703 );
1704 Ok(())
1705 }
1706
1707 #[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
1710 pub fn set_subs_no_deposit(
1711 who: &T::AccountId,
1712 subs: Vec<(T::AccountId, Data)>,
1713 ) -> DispatchResult {
1714 let mut sub_accounts = BoundedVec::<T::AccountId, T::MaxSubAccounts>::default();
1715 for (sub, name) in subs {
1716 SuperOf::<T>::insert(&sub, (who.clone(), name));
1717 sub_accounts
1718 .try_push(sub)
1719 .expect("benchmark should not pass more than T::MaxSubAccounts");
1720 }
1721 SubsOf::<T>::insert::<
1722 &T::AccountId,
1723 (BalanceOf<T>, BoundedVec<T::AccountId, T::MaxSubAccounts>),
1724 >(&who, (Zero::zero(), sub_accounts));
1725 Ok(())
1726 }
1727}