referrerpolicy=no-referrer-when-downgrade

pallet_identity/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! # Identity Pallet
19//!
20//! - [`Config`]
21//! - [`Call`]
22//!
23//! ## Overview
24//!
25//! A federated naming system, allowing for multiple registrars to be added from a specified origin.
26//! Registrars can set a fee to provide identity-verification service. Anyone can put forth a
27//! proposed identity for a fixed deposit and ask for review by any number of registrars (paying
28//! each of their fees). Registrar judgements are given as an `enum`, allowing for sophisticated,
29//! multi-tier opinions.
30//!
31//! Some judgements are identified as *sticky*, which means they cannot be removed except by
32//! complete removal of the identity, or by the registrar. Judgements are allowed to represent a
33//! portion of funds that have been reserved for the registrar.
34//!
35//! A super-user can remove accounts and in doing so, slash the deposit.
36//!
37//! All accounts may also have a limited number of sub-accounts which may be specified by the owner;
38//! by definition, these have equivalent ownership and each has an individual name.
39//!
40//! The number of registrars should be limited, and the deposit made sufficiently large, to ensure
41//! no state-bloat attack is viable.
42//!
43//! ### Usernames
44//!
45//! The pallet provides functionality for username authorities to issue usernames, which are
46//! independent of the identity information functionality; an account can set:
47//! - an identity without setting a username
48//! - a username without setting an identity
49//! - an identity and a username
50//!
51//! The username functionality implemented in this pallet is meant to be a user friendly lookup of
52//! accounts. There are mappings in both directions, "account -> username" and "username ->
53//! account".
54//!
55//! Usernames are granted by authorities and grouped by suffix, with each suffix being administered
56//! by one authority. To grant a username, a username authority can either:
57//! - be given an allocation by governance of a specific amount of usernames to issue for free,
58//!   without any deposit associated with storage costs;
59//! - put up a deposit for each username it issues (usually a subsidized, reduced deposit, relative
60//!   to other deposits in the system)
61//!
62//! Users can have multiple usernames that map to the same `AccountId`, however one `AccountId` can
63//! only map to a single username, known as the _primary_. This primary username will be the result
64//! of a lookup in the [UsernameOf] map for any given account.
65//!
66//! ## Interface
67//!
68//! ### Dispatchable Functions
69//!
70//! #### For General Users
71//! * `set_identity` - Set the associated identity of an account; a small deposit is reserved if not
72//!   already taken.
73//! * `clear_identity` - Remove an account's associated identity; the deposit is returned.
74//! * `request_judgement` - Request a judgement from a registrar, paying a fee.
75//! * `cancel_request` - Cancel the previous request for a judgement.
76//! * `accept_username` - Accept a username issued by a username authority.
77//! * `remove_expired_approval` - Remove a username that was issued but never accepted.
78//! * `set_primary_username` - Set a given username as an account's primary.
79//! * `remove_username` - Remove a username after its grace period has ended.
80//!
81//! #### For General Users with Sub-Identities
82//! * `set_subs` - Set the sub-accounts of an identity.
83//! * `add_sub` - Add a sub-identity to an identity.
84//! * `remove_sub` - Remove a sub-identity of an identity.
85//! * `rename_sub` - Rename a sub-identity of an identity.
86//! * `quit_sub` - Remove a sub-identity of an identity (called by the sub-identity).
87//!
88//! #### For Registrars
89//! * `set_fee` - Set the fee required to be paid for a judgement to be given by the registrar.
90//! * `set_fields` - Set the fields that a registrar cares about in their judgements.
91//! * `provide_judgement` - Provide a judgement to an identity.
92//!
93//! #### For Username Authorities
94//! * `set_username_for` - Set a username for a given account. The account must approve it.
95//! * `unbind_username` - Start the grace period for a username.
96//!
97//! #### For Superusers
98//! * `add_registrar` - Add a new registrar to the system.
99//! * `kill_identity` - Forcibly remove the associated identity; the deposit is lost.
100//! * `add_username_authority` - Add an account with the ability to issue usernames.
101//! * `remove_username_authority` - Remove an account with the ability to issue usernames.
102//! * `kill_username` - Forcibly remove a username.
103//!
104//! [`Call`]: ./enum.Call.html
105//! [`Config`]: ./trait.Config.html
106
107#![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		/// The overarching event type.
176		#[allow(deprecated)]
177		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
178
179		/// The currency trait.
180		type Currency: ReservableCurrency<Self::AccountId>;
181
182		/// The amount held on deposit for a registered identity.
183		#[pallet::constant]
184		type BasicDeposit: Get<BalanceOf<Self>>;
185
186		/// The amount held on deposit per encoded byte for a registered identity.
187		#[pallet::constant]
188		type ByteDeposit: Get<BalanceOf<Self>>;
189
190		/// The amount held on deposit per registered username. This value should change only in
191		/// runtime upgrades with proper migration of existing deposits.
192		#[pallet::constant]
193		type UsernameDeposit: Get<BalanceOf<Self>>;
194
195		/// The amount held on deposit for a registered subaccount. This should account for the fact
196		/// that one storage item's value will increase by the size of an account ID, and there will
197		/// be another trie item whose value is the size of an account ID plus 32 bytes.
198		#[pallet::constant]
199		type SubAccountDeposit: Get<BalanceOf<Self>>;
200
201		/// The maximum number of sub-accounts allowed per identified account.
202		#[pallet::constant]
203		type MaxSubAccounts: Get<u32>;
204
205		/// Structure holding information about an identity.
206		type IdentityInformation: IdentityInformationProvider;
207
208		/// Maximum number of registrars allowed in the system. Needed to bound the complexity
209		/// of, e.g., updating judgements.
210		#[pallet::constant]
211		type MaxRegistrars: Get<u32>;
212
213		/// What to do with slashed funds.
214		type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;
215
216		/// The origin which may forcibly set or remove a name. Root can always do this.
217		type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
218
219		/// The origin which may add or remove registrars. Root can always do this.
220		type RegistrarOrigin: EnsureOrigin<Self::RuntimeOrigin>;
221
222		/// Signature type for pre-authorizing usernames off-chain.
223		///
224		/// Can verify whether an `Self::SigningPublicKey` created a signature.
225		type OffchainSignature: Verify<Signer = Self::SigningPublicKey> + Parameter;
226
227		/// Public key that corresponds to an on-chain `Self::AccountId`.
228		type SigningPublicKey: IdentifyAccount<AccountId = Self::AccountId>;
229
230		/// The origin which may add or remove username authorities. Root can always do this.
231		type UsernameAuthorityOrigin: EnsureOrigin<Self::RuntimeOrigin>;
232
233		/// The number of blocks within which a username grant must be accepted.
234		#[pallet::constant]
235		type PendingUsernameExpiration: Get<BlockNumberFor<Self>>;
236
237		/// The number of blocks that must pass to enable the permanent deletion of a username by
238		/// its respective authority.
239		#[pallet::constant]
240		type UsernameGracePeriod: Get<BlockNumberFor<Self>>;
241
242		/// The maximum length of a suffix.
243		#[pallet::constant]
244		type MaxSuffixLength: Get<u32>;
245
246		/// The maximum length of a username, including its suffix and any system-added delimiters.
247		#[pallet::constant]
248		type MaxUsernameLength: Get<u32>;
249
250		/// A set of helper functions for benchmarking.
251		/// The default configuration `()` uses the `SR25519` signature schema.
252		#[cfg(feature = "runtime-benchmarks")]
253		type BenchmarkHelper: BenchmarkHelper<Self::SigningPublicKey, Self::OffchainSignature>;
254
255		/// Weight information for extrinsics in this pallet.
256		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	/// Information that is pertinent to identify the entity behind an account. First item is the
266	/// registration, second is the account's primary username.
267	///
268	/// TWOX-NOTE: OK ― `AccountId` is a secure hash.
269	#[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	/// Identifies the primary username of an account.
279	#[pallet::storage]
280	pub type UsernameOf<T: Config> =
281		StorageMap<_, Twox64Concat, T::AccountId, Username<T>, OptionQuery>;
282
283	/// The super-identity of an alternative "sub" identity together with its name, within that
284	/// context. If the account is not some other account's sub-identity, then just `None`.
285	#[pallet::storage]
286	pub type SuperOf<T: Config> =
287		StorageMap<_, Blake2_128Concat, T::AccountId, (T::AccountId, Data), OptionQuery>;
288
289	/// Alternative "sub" identities of this account.
290	///
291	/// The first item is the deposit, the second is a vector of the accounts.
292	///
293	/// TWOX-NOTE: OK ― `AccountId` is a secure hash.
294	#[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	/// The set of registrars. Not expected to get very big as can only be added through a
304	/// special origin (likely a council motion).
305	///
306	/// The index into this can be cast to `RegistrarIndex` to get a valid value.
307	#[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	/// A map of the accounts who are authorized to grant usernames.
324	#[pallet::storage]
325	pub type AuthorityOf<T: Config> =
326		StorageMap<_, Twox64Concat, Suffix<T>, AuthorityProperties<T::AccountId>, OptionQuery>;
327
328	/// Reverse lookup from `username` to the `AccountId` that has registered it and the provider of
329	/// the username. The `owner` value should be a key in the `UsernameOf` map, but it may not if
330	/// the user has cleared their username or it has been removed.
331	///
332	/// Multiple usernames may map to the same `AccountId`, but `UsernameOf` will only map to one
333	/// primary username.
334	#[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	/// Usernames that an authority has granted, but that the account controller has not confirmed
344	/// that they want it. Used primarily in cases where the `AccountId` cannot provide a signature
345	/// because they are a pure proxy, multisig, etc. In order to confirm it, they should call
346	/// [accept_username](`Call::accept_username`).
347	///
348	/// First tuple item is the account and second is the acceptance deadline.
349	#[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	/// Usernames for which the authority that granted them has started the removal process by
359	/// unbinding them. Each unbinding username maps to its grace period expiry, which is the first
360	/// block in which the username could be deleted through a
361	/// [remove_username](`Call::remove_username`) call.
362	#[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		/// Too many subs-accounts.
369		TooManySubAccounts,
370		/// Account isn't found.
371		NotFound,
372		/// Account isn't named.
373		NotNamed,
374		/// Empty index.
375		EmptyIndex,
376		/// Fee is changed.
377		FeeChanged,
378		/// No identity found.
379		NoIdentity,
380		/// Sticky judgement.
381		StickyJudgement,
382		/// Judgement given.
383		JudgementGiven,
384		/// Invalid judgement.
385		InvalidJudgement,
386		/// The index is invalid.
387		InvalidIndex,
388		/// The target is invalid.
389		InvalidTarget,
390		/// Maximum amount of registrars reached. Cannot add any more.
391		TooManyRegistrars,
392		/// Account ID is already named.
393		AlreadyClaimed,
394		/// Sender is not a sub-account.
395		NotSub,
396		/// Sub-account isn't owned by sender.
397		NotOwned,
398		/// The provided judgement was for a different identity.
399		JudgementForDifferentIdentity,
400		/// Error that occurs when there is an issue paying for judgement.
401		JudgementPaymentFailed,
402		/// The provided suffix is too long.
403		InvalidSuffix,
404		/// The sender does not have permission to issue a username.
405		NotUsernameAuthority,
406		/// The authority cannot allocate any more usernames.
407		NoAllocation,
408		/// The signature on a username was not valid.
409		InvalidSignature,
410		/// Setting this username requires a signature, but none was provided.
411		RequiresSignature,
412		/// The username does not meet the requirements.
413		InvalidUsername,
414		/// The username is already taken.
415		UsernameTaken,
416		/// The requested username does not exist.
417		NoUsername,
418		/// The username cannot be forcefully removed because it can still be accepted.
419		NotExpired,
420		/// The username cannot be removed because it's still in the grace period.
421		TooEarly,
422		/// The username cannot be removed because it is not unbinding.
423		NotUnbinding,
424		/// The username cannot be unbound because it is already unbinding.
425		AlreadyUnbinding,
426		/// The action cannot be performed because of insufficient privileges (e.g. authority
427		/// trying to unbind a username provided by the system).
428		InsufficientPrivileges,
429	}
430
431	#[pallet::event]
432	#[pallet::generate_deposit(pub(super) fn deposit_event)]
433	pub enum Event<T: Config> {
434		/// A name was set or reset (which will remove all judgements).
435		IdentitySet { who: T::AccountId },
436		/// A name was cleared, and the given balance returned.
437		IdentityCleared { who: T::AccountId, deposit: BalanceOf<T> },
438		/// A name was removed and the given balance slashed.
439		IdentityKilled { who: T::AccountId, deposit: BalanceOf<T> },
440		/// A judgement was asked from a registrar.
441		JudgementRequested { who: T::AccountId, registrar_index: RegistrarIndex },
442		/// A judgement request was retracted.
443		JudgementUnrequested { who: T::AccountId, registrar_index: RegistrarIndex },
444		/// A judgement was given by a registrar.
445		JudgementGiven { target: T::AccountId, registrar_index: RegistrarIndex },
446		/// A registrar was added.
447		RegistrarAdded { registrar_index: RegistrarIndex },
448		/// A registrar was removed.
449		RegistrarRemoved { registrar_index: RegistrarIndex },
450		/// A sub-identity was added to an identity and the deposit paid.
451		SubIdentityAdded { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
452		/// An account's sub-identities were set (in bulk).
453		SubIdentitiesSet { main: T::AccountId, number_of_subs: u32, new_deposit: BalanceOf<T> },
454		/// A given sub-account's associated name was changed by its super-identity.
455		SubIdentityRenamed { sub: T::AccountId, main: T::AccountId },
456		/// A sub-identity was removed from an identity and the deposit freed.
457		SubIdentityRemoved { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
458		/// A sub-identity was cleared, and the given deposit repatriated from the
459		/// main identity account to the sub-identity account.
460		SubIdentityRevoked { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
461		/// A username authority was added.
462		AuthorityAdded { authority: T::AccountId },
463		/// A username authority was removed.
464		AuthorityRemoved { authority: T::AccountId },
465		/// A username was set for `who`.
466		UsernameSet { who: T::AccountId, username: Username<T> },
467		/// A username was queued, but `who` must accept it prior to `expiration`.
468		UsernameQueued { who: T::AccountId, username: Username<T>, expiration: BlockNumberFor<T> },
469		/// A queued username passed its expiration without being claimed and was removed.
470		PreapprovalExpired { whose: T::AccountId },
471		/// A username was set as a primary and can be looked up from `who`.
472		PrimaryUsernameSet { who: T::AccountId, username: Username<T> },
473		/// A dangling username (as in, a username corresponding to an account that has removed its
474		/// identity) has been removed.
475		DanglingUsernameRemoved { who: T::AccountId, username: Username<T> },
476		/// A username has been unbound.
477		UsernameUnbound { username: Username<T> },
478		/// A username has been removed.
479		UsernameRemoved { username: Username<T> },
480		/// A username has been killed.
481		UsernameKilled { username: Username<T> },
482	}
483
484	#[pallet::call]
485	/// Identity pallet declaration.
486	impl<T: Config> Pallet<T> {
487		/// Add a registrar to the system.
488		///
489		/// The dispatch origin for this call must be `T::RegistrarOrigin`.
490		///
491		/// - `account`: the account of the registrar.
492		///
493		/// Emits `RegistrarAdded` if successful.
494		#[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		/// Remove a registrar from the system.
522		///
523		/// The dispatch origin for this call must be `T::RegistrarOrigin`.
524		///
525		/// The registrar's slot is tombstoned (set to `None`) rather than removed, so that the
526		/// `RegistrarIndex` of every other registrar — and any judgements already recorded against
527		/// them — stays stable. The freed index is not reused by `add_registrar`, so each removal
528		/// permanently consumes one slot against `MaxRegistrars` (reusing the slot would let a new
529		/// registrar inherit an index that historical judgements still reference).
530		///
531		/// Deposits reserved by pending `request_judgement` calls against this registrar are
532		/// **not** returned; once the registrar is removed `provide_judgement` can no longer
533		/// release them, so affected users should reclaim their funds manually with
534		/// `cancel_request`.
535		///
536		/// - `index`: the index of the registrar to remove.
537		///
538		/// Emits `RegistrarRemoved` if successful.
539		#[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		/// Set an account's identity information and reserve the appropriate deposit.
561		///
562		/// If the account already has identity information, the deposit is taken as part payment
563		/// for the new deposit.
564		///
565		/// The dispatch origin for this call must be _Signed_.
566		///
567		/// - `info`: The identity information.
568		///
569		/// Emits `IdentitySet` if successful.
570		#[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					// Only keep non-positive judgements.
581					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		/// Set the sub-accounts of the sender.
605		///
606		/// Payment: Any aggregate balance reserved by previous `set_subs` calls will be returned
607		/// and an amount `SubAccountDeposit` will be reserved for each item in `subs`.
608		///
609		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
610		/// identity.
611		///
612		/// - `subs`: The identity's (new) sub-accounts.
613		// TODO: This whole extrinsic screams "not optimized". For example we could
614		// filter any overlap between new and old subs, and avoid reading/writing
615		// to those values... We could also ideally avoid needing to write to
616		// N storage items for N sub accounts. Right now the weight on this function
617		// is a large overestimate due to the fact that it could potentially write
618		// to 2 x T::MaxSubAccounts::get().
619		#[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			// do nothing if they're equal.
648
649			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) // P: Real number of old accounts removed.
673					// S: New subs added
674					.saturating_add(T::WeightInfo::set_subs_new(new_subs as u32)),
675			)
676			.into())
677		}
678
679		/// Clear an account's identity info and all sub-accounts and return all deposits.
680		///
681		/// Payment: All reserved balances on the account are returned.
682		///
683		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
684		/// identity.
685		///
686		/// Emits `IdentityCleared` if successful.
687		#[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		/// Request a judgement from a registrar.
716		///
717		/// Payment: At most `max_fee` will be reserved for payment to the registrar if judgement
718		/// given.
719		///
720		/// The dispatch origin for this call must be _Signed_ and the sender must have a
721		/// registered identity.
722		///
723		/// - `reg_index`: The index of the registrar whose judgement is requested.
724		/// - `max_fee`: The maximum fee that may be paid. This should just be auto-populated as:
725		///
726		/// ```nocompile
727		/// Registrars::<T>::get().get(reg_index).unwrap().fee
728		/// ```
729		///
730		/// Emits `JudgementRequested` if successful.
731		#[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(&reg_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		/// Cancel a previous request.
775		///
776		/// Payment: A previously reserved deposit is returned on success.
777		///
778		/// The dispatch origin for this call must be _Signed_ and the sender must have a
779		/// registered identity.
780		///
781		/// - `reg_index`: The index of the registrar whose judgement is no longer requested.
782		///
783		/// Emits `JudgementUnrequested` if successful.
784		#[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(&reg_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		/// Set the fee required for a judgement to be requested from a registrar.
817		///
818		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
819		/// of the registrar whose index is `index`.
820		///
821		/// - `index`: the index of the registrar whose fee is to be set.
822		/// - `fee`: the new fee.
823		#[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		/// Change the account associated with a registrar.
850		///
851		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
852		/// of the registrar whose index is `index`.
853		///
854		/// - `index`: the index of the registrar whose fee is to be set.
855		/// - `new`: the new account ID.
856		#[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		/// Set the field information for a registrar.
884		///
885		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
886		/// of the registrar whose index is `index`.
887		///
888		/// - `index`: the index of the registrar whose fee is to be set.
889		/// - `fields`: the fields that the registrar concerns themselves with.
890		#[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		/// Provide a judgement for an account's identity.
914		///
915		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
916		/// of the registrar whose index is `reg_index`.
917		///
918		/// - `reg_index`: the index of the registrar whose judgement is being made.
919		/// - `target`: the account whose identity the judgement is upon. This must be an account
920		///   with a registered identity.
921		/// - `judgement`: the judgement of the registrar of index `reg_index` about `target`.
922		/// - `identity`: The hash of the [`IdentityInformationProvider`] for that the judgement is
923		///   provided.
924		///
925		/// Note: Judgements do not apply to a username.
926		///
927		/// Emits `JudgementGiven` if successful.
928		#[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(&reg_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		/// Remove an account's identity and sub-account information and slash the deposits.
979		///
980		/// Payment: Reserved balances from `set_subs` and `set_identity` are slashed and handled by
981		/// `Slash`. Verification request deposits are not returned; they should be cancelled
982		/// manually using `cancel_request`.
983		///
984		/// The dispatch origin for this call must match `T::ForceOrigin`.
985		///
986		/// - `target`: the account whose identity the judgement is upon. This must be an account
987		///   with a registered identity.
988		///
989		/// Emits `IdentityKilled` if successful.
990		#[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			// Figure out who we're meant to be clearing.
1002			let target = T::Lookup::lookup(target)?;
1003			// Grab their deposit (and check that they have one).
1004			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			// Slash their deposit from them.
1011			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		/// Add the given account to the sender's subs.
1021		///
1022		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
1023		/// to the sender.
1024		///
1025		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
1026		/// sub identity of `sub`.
1027		#[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			// Check if it's already claimed as sub-identity.
1039			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 there is space and that the deposit is paid.
1043				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		/// Alter the associated name of the given sub-account.
1060		///
1061		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
1062		/// sub identity of `sub`.
1063		#[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		/// Remove the given account from the sender's subs.
1081		///
1082		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
1083		/// to the sender.
1084		///
1085		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
1086		/// sub identity of `sub`.
1087		#[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		/// Remove the sender as a sub-account.
1108		///
1109		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
1110		/// to the sender (*not* the original depositor).
1111		///
1112		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
1113		/// super-identity.
1114		///
1115		/// NOTE: This should not normally be used, but is provided in the case that the non-
1116		/// controller of an account is maliciously registered as a sub-account.
1117		#[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		/// Add an `AccountId` with permission to grant usernames with a given `suffix` appended.
1138		///
1139		/// The authority can grant up to `allocation` usernames. To top up the allocation or
1140		/// change the account used to grant usernames, this call can be used with the updated
1141		/// parameters to overwrite the existing configuration.
1142		#[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			// We don't need to check the length because it gets checked when casting into a
1153			// `BoundedVec`.
1154			Self::validate_suffix(&suffix)?;
1155			let suffix = Suffix::<T>::try_from(suffix).map_err(|_| Error::<T>::InvalidSuffix)?;
1156			// The call is `UsernameAuthorityOrigin` guarded, overwrite the old entry if it exists.
1157			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		/// Remove `authority` from the username authorities.
1166		#[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		/// Set the username for `who`. Must be called by a username authority.
1184		///
1185		/// If `use_allocation` is set, the authority must have a username allocation available to
1186		/// spend. Otherwise, the authority will need to put up a deposit for registering the
1187		/// username.
1188		///
1189		/// Users can either pre-sign their usernames or
1190		/// accept them later.
1191		///
1192		/// Usernames must:
1193		///   - Only contain lowercase ASCII characters or digits.
1194		///   - When combined with the suffix of the issuing authority be _less than_ the
1195		///     `MaxUsernameLength`.
1196		#[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			// Ensure origin is a Username Authority and has an allocation. Decrement their
1206			// allocation by one.
1207			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			// Usernames must be unique. Ensure it's not taken.
1231			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			// Insert or queue.
1241			let who = T::Lookup::lookup(who)?;
1242			if let Some(s) = signature {
1243				// Account has pre-signed an authorization. Verify the signature provided and grant
1244				// the username directly.
1245				Self::validate_signature(&bounded_username[..], &s, &who)?;
1246				Self::insert_username(&who, bounded_username, provider);
1247			} else {
1248				// The user must accept the username, therefore, queue it.
1249				Self::queue_acceptance(&who, bounded_username, provider);
1250			}
1251			Ok(())
1252		}
1253
1254		/// Accept a given username that an `authority` granted. The call must include the full
1255		/// username, as in `username.suffix`.
1256		#[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		/// Remove an expired username approval. The username was approved by an authority but never
1272		/// accepted by the user and must now be beyond its expiration. The call must include the
1273		/// full username, as in `username.suffix`.
1274		#[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						// We don't refund the allocation, it is lost, but we refund some weight.
1297						T::WeightInfo::remove_expired_approval(1)
1298					},
1299					Provider::System => {
1300						// Usernames added by the system shouldn't ever be expired.
1301						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		/// Set a given username as the primary. The username should include the suffix.
1312		#[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			// ensure `username` maps to `origin` (i.e. has already been set by an authority).
1316			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		/// Start the process of removing a username by placing it in the unbinding usernames map.
1326		/// Once the grace period has passed, the username can be deleted by calling
1327		/// [remove_username](crate::Call::remove_username).
1328		#[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		/// Permanently delete a username which has been unbinding for longer than the grace period.
1358		/// Caller is refunded the fee if the username expired and the removal was successful.
1359		#[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			// If this is the primary username, remove the entry from the account -> username map.
1374			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					// We don't refund the allocation, it is lost.
1394				},
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		/// Call with [ForceOrigin](crate::Config::ForceOrigin) privileges which deletes a username
1402		/// and slashes any deposit associated with it.
1403		#[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			// If this is the primary username, remove the entry from the account -> username map.
1413			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					// We don't refund the allocation, it is lost, but we do refund some weight.
1437					T::WeightInfo::kill_username(1)
1438				},
1439				Provider::System => {
1440					// Force origin can remove system usernames.
1441					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	/// Get the subs of an account.
1452	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	/// Calculate the deposit required for a number of `sub` accounts.
1461	fn subs_deposit(subs: u32) -> BalanceOf<T> {
1462		T::SubAccountDeposit::get().saturating_mul(BalanceOf::<T>::from(subs))
1463	}
1464
1465	/// Take the `current` deposit that `who` is holding, and update it to a `new` one.
1466	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	/// Check if the account has corresponding identity information by the identity field.
1481	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	/// Calculate the deposit required for an identity.
1490	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	/// Validate that a username conforms to allowed characters/format.
1497	///
1498	/// The function will validate the characters in `username`. It is expected to pass a fully
1499	/// formatted username here (i.e. "username.suffix"). The suffix is also separately validated
1500	/// and returned by this function.
1501	fn validate_username(username: &Vec<u8>) -> Result<Suffix<T>, DispatchError> {
1502		// Verify input length before allocating a Vec with the user's input.
1503		ensure!(
1504			username.len() <= T::MaxUsernameLength::get() as usize,
1505			Error::<T>::InvalidUsername
1506		);
1507
1508		// Usernames cannot be empty.
1509		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		// Username must be lowercase and alphanumeric.
1516		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	/// Return the suffix of a username, if it is valid.
1531	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	/// Validate that a suffix conforms to allowed characters/format.
1541	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	/// Validate a signature. Supports signatures on raw `data` or `data` wrapped in HTML `<Bytes>`.
1552	pub fn validate_signature(
1553		data: &[u8],
1554		signature: &T::OffchainSignature,
1555		signer: &T::AccountId,
1556	) -> DispatchResult {
1557		// Happy path, user has signed the raw data.
1558		if signature.verify(data, &signer) {
1559			return Ok(());
1560		}
1561		// NOTE: for security reasons modern UIs implicitly wrap the data requested to sign into
1562		// `<Bytes> + data + </Bytes>`, so why we support both wrapped and raw versions.
1563		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	/// A username has met all conditions. Insert the relevant storage items.
1576	pub fn insert_username(who: &T::AccountId, username: Username<T>, provider: ProviderOf<T>) {
1577		// Check if they already have a primary. If so, leave it. If not, set it.
1578		// Likewise, check if they have an identity. If not, give them a minimal one.
1579		let (primary_username, new_is_primary) = match UsernameOf::<T>::get(&who) {
1580			// User has an existing Identity and a primary username. Leave it.
1581			Some(primary) => (primary, false),
1582			// User has an Identity but no primary. Set the new one as primary.
1583			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		// Enter in username map.
1591		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	/// A username was granted by an authority, but must be accepted by `who`. Put the username
1599	/// into a queue for acceptance.
1600	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	/// Reap an identity, clearing associated storage items and refunding any deposits. This
1608	/// function is very similar to (a) `clear_identity`, but called on a `target` account instead
1609	/// of self; and (b) `kill_identity`, but without imposing a slash.
1610	///
1611	/// Parameters:
1612	/// - `target`: The account for which to reap identity state.
1613	///
1614	/// Return type is a tuple of the number of registrars, `IdentityInfo` bytes, and sub accounts,
1615	/// respectively.
1616	///
1617	/// NOTE: This function is here temporarily for migration of Identity info from the Polkadot
1618	/// Relay Chain into a system parachain. It will be removed after the migration.
1619	pub fn reap_identity(who: &T::AccountId) -> Result<(u32, u32, u32), DispatchError> {
1620		// `take` any storage items keyed by `target`
1621		// identity
1622		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		// subs
1627		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		// unreserve any deposits
1634		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	/// Update the deposits held by `target` for its identity info.
1641	///
1642	/// Parameters:
1643	/// - `target`: The account for which to update deposits.
1644	///
1645	/// Return type is a tuple of the new Identity and Subs deposits, respectively.
1646	///
1647	/// NOTE: This function is here temporarily for migration of Identity info from the Polkadot
1648	/// Relay Chain into a system parachain. It will be removed after the migration.
1649	pub fn poke_deposit(
1650		target: &T::AccountId,
1651	) -> Result<(BalanceOf<T>, BalanceOf<T>), DispatchError> {
1652		// Identity Deposit
1653		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				// Calculate what deposit should be
1658				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				// Update account
1664				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			// If the item doesn't exist, there is no "old" deposit, and the new one is zero, so no
1683			// need to call rejig, it'd just be zero -> zero.
1684			Zero::zero()
1685		};
1686		Ok((new_id_deposit, new_subs_deposit))
1687	}
1688
1689	/// Set an identity with zero deposit. Used for benchmarking and XCM emulator tests that involve
1690	/// `rejig_deposit`.
1691	#[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	/// Set subs with zero deposit and default name. Only used for benchmarks that involve
1708	/// `rejig_deposit`.
1709	#[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}