git.delta.rocks / unique-network / refs/commits / f8930f84e9cd

difftreelog

feat(identity) fork + publicize private fields

Fahrrader2022-12-27parent: #3ce5f80.patch.diff
in: master

14 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4026,7 +4026,7 @@
  "pallet-elections-phragmen",
  "pallet-fast-unstake",
  "pallet-grandpa",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36)",
  "pallet-im-online",
  "pallet-indices",
  "pallet-membership",
@@ -5322,7 +5322,7 @@
  "pallet-evm-transaction-payment",
  "pallet-foreign-assets",
  "pallet-fungible",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev",
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
@@ -5777,7 +5777,7 @@
 
 [[package]]
 name = "pallet-collator-selection"
-version = "3.0.0"
+version = "4.0.0"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -5885,6 +5885,7 @@
  "frame-support",
  "frame-system",
  "pallet-evm",
+ "pallet-identity 4.0.0-dev",
  "parity-scale-codec 3.2.1",
  "scale-info",
  "sp-core",
@@ -6184,6 +6185,23 @@
 [[package]]
 name = "pallet-identity"
 version = "4.0.0-dev"
+dependencies = [
+ "enumflags2",
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "parity-scale-codec 3.2.1",
+ "scale-info",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
+name = "pallet-identity"
+version = "4.0.0-dev"
 source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51"
 dependencies = [
  "enumflags2",
@@ -8137,7 +8155,7 @@
  "pallet-elections-phragmen",
  "pallet-fast-unstake",
  "pallet-grandpa",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36)",
  "pallet-im-online",
  "pallet-indices",
  "pallet-membership",
@@ -8912,7 +8930,7 @@
  "pallet-evm-transaction-payment",
  "pallet-foreign-assets",
  "pallet-fungible",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev",
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
@@ -9353,7 +9371,7 @@
  "pallet-democracy",
  "pallet-elections-phragmen",
  "pallet-grandpa",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36)",
  "pallet-im-online",
  "pallet-indices",
  "pallet-membership",
@@ -13144,7 +13162,7 @@
  "pallet-evm-transaction-payment",
  "pallet-foreign-assets",
  "pallet-fungible",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev",
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
@@ -13789,7 +13807,7 @@
  "pallet-elections-phragmen",
  "pallet-fast-unstake",
  "pallet-grandpa",
- "pallet-identity",
+ "pallet-identity 4.0.0-dev (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36)",
  "pallet-im-online",
  "pallet-indices",
  "pallet-membership",
modifiedpallets/collator-selection/Cargo.tomldiffbeforeafterboth
--- a/pallets/collator-selection/Cargo.toml
+++ b/pallets/collator-selection/Cargo.toml
@@ -1,8 +1,8 @@
 [package]
 name = "pallet-collator-selection"
-version = "3.0.0"
+version = "4.0.0"
 description = "Simple staking pallet with a fixed stake."
-authors = ["Unique Network <support@uniquenetwork.io>"]
+authors = ["Parity Technologies <admin@parity.io>", "Unique Network <support@uniquenetwork.io>"]
 edition = "2021"
 homepage = "https://unique.network"
 repository = "https://github.com/UniqueNetwork/unique-chain"
modifiedpallets/data-management/Cargo.tomldiffbeforeafterboth
--- a/pallets/data-management/Cargo.toml
+++ b/pallets/data-management/Cargo.toml
@@ -16,6 +16,7 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
 sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+pallet-identity = { default-features = false, path = "../identity" }
 pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" }
 fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" }
 
modifiedpallets/data-management/src/lib.rsdiffbeforeafterboth
--- a/pallets/data-management/src/lib.rs
+++ b/pallets/data-management/src/lib.rs
@@ -34,9 +34,10 @@
 	use sp_std::vec::Vec;
 	use super::weights::WeightInfo;
 	use pallet_evm::{PrecompileHandle, Pallet as PalletEvm};
+	use pallet_identity::Registration;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_evm::Config {
+	pub trait Config: frame_system::Config + pallet_evm::Config + pallet_identity::Config {
 		/// Weights
 		type WeightInfo: WeightInfo;
 		/// The overarching event type.
@@ -149,6 +150,23 @@
 			}
 			Ok(())
 		}
+
+		/// Insert or remove identities.
+		#[pallet::call_index(5)]
+		#[pallet::weight(<SelfWeightOf<T>>::insert_events(identities.len() as u32))] // todo:collator weight
+		pub fn insert_identities(
+			origin: OriginFor<T>,
+			identities: Vec<(
+				T::AccountId,
+				Option<Registration<pallet_identity::BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields>>,
+			)>,
+		) -> DispatchResult {
+			ensure_root(origin)?;
+			for identity in identities {
+				<pallet_identity::IdentityOf<T>>::set(identity.0, identity.1);
+			}
+			Ok(())
+		}
 	}
 
 	/// Implements [`pallet_evm::OnMethodCall`], which reserves accounts with pending migration
addedpallets/identity/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/Cargo.toml
@@ -0,0 +1,47 @@
+[package]
+name = "pallet-identity"
+version = "4.0.0-dev"
+authors = ["Parity Technologies <admin@parity.io>", "Unique Network <support@uniquenetwork.io>"]
+edition = "2021"
+license = "Apache-2.0"
+homepage = "https://substrate.io"
+repository = "https://github.com/paritytech/substrate/"
+description = "FRAME identity management pallet"
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] }
+enumflags2 = { version = "0.7.4" }
+scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
+frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+sp-io = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+sp-runtime = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+sp-std = { version = "5.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+
+[dev-dependencies]
+pallet-balances = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+sp-core = { version = "7.0.0", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
+
+[features]
+default = ["std"]
+std = [
+	"codec/std",
+	"frame-benchmarking?/std",
+	"frame-support/std",
+	"frame-system/std",
+	"scale-info/std",
+	"sp-io/std",
+	"sp-runtime/std",
+	"sp-std/std",
+]
+runtime-benchmarks = [
+	"frame-benchmarking/runtime-benchmarks",
+	"frame-support/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+]
+try-runtime = ["frame-support/try-runtime"]
addedpallets/identity/README.mddiffbeforeafterboth

no content

addedpallets/identity/src/benchmarking.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/src/benchmarking.rs
@@ -0,0 +1,462 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Identity pallet benchmarking.
+
+#![cfg(feature = "runtime-benchmarks")]
+
+use super::*;
+
+use crate::Pallet as Identity;
+use frame_benchmarking::{account, benchmarks, whitelisted_caller};
+use frame_support::{
+	ensure,
+	traits::{EnsureOrigin, Get},
+};
+use frame_system::RawOrigin;
+use sp_runtime::traits::Bounded;
+
+const SEED: u32 = 0;
+
+fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
+	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
+}
+
+// Adds `r` registrars to the Identity Pallet. These registrars will have set fees and fields.
+fn add_registrars<T: Config>(r: u32) -> Result<(), &'static str> {
+	for i in 0..r {
+		let registrar: T::AccountId = account("registrar", i, SEED);
+		let registrar_lookup = T::Lookup::unlookup(registrar.clone());
+		let _ = T::Currency::make_free_balance_be(&registrar, BalanceOf::<T>::max_value());
+		let registrar_origin = T::RegistrarOrigin::successful_origin();
+		Identity::<T>::add_registrar(registrar_origin, registrar_lookup)?;
+		Identity::<T>::set_fee(RawOrigin::Signed(registrar.clone()).into(), i, 10u32.into())?;
+		let fields =
+			IdentityFields(
+				IdentityField::Display |
+					IdentityField::Legal | IdentityField::Web |
+					IdentityField::Riot | IdentityField::Email |
+					IdentityField::PgpFingerprint |
+					IdentityField::Image | IdentityField::Twitter,
+			);
+		Identity::<T>::set_fields(RawOrigin::Signed(registrar.clone()).into(), i, fields)?;
+	}
+
+	assert_eq!(Registrars::<T>::get().len(), r as usize);
+	Ok(())
+}
+
+// Create `s` sub-accounts for the identity of `who` and return them.
+// Each will have 32 bytes of raw data added to it.
+fn create_sub_accounts<T: Config>(
+	who: &T::AccountId,
+	s: u32,
+) -> Result<Vec<(T::AccountId, Data)>, &'static str> {
+	let mut subs = Vec::new();
+	let who_origin = RawOrigin::Signed(who.clone());
+	let data = Data::Raw(vec![0; 32].try_into().unwrap());
+
+	for i in 0..s {
+		let sub_account = account("sub", i, SEED);
+		subs.push((sub_account, data.clone()));
+	}
+
+	// Set identity so `set_subs` does not fail.
+	if IdentityOf::<T>::get(who).is_none() {
+		let _ = T::Currency::make_free_balance_be(who, BalanceOf::<T>::max_value() / 2u32.into());
+		let info = create_identity_info::<T>(1);
+		Identity::<T>::set_identity(who_origin.into(), Box::new(info))?;
+	}
+
+	Ok(subs)
+}
+
+// Adds `s` sub-accounts to the identity of `who`. Each will have 32 bytes of raw data added to it.
+// This additionally returns the vector of sub-accounts so it can be modified if needed.
+fn add_sub_accounts<T: Config>(
+	who: &T::AccountId,
+	s: u32,
+) -> Result<Vec<(T::AccountId, Data)>, &'static str> {
+	let who_origin = RawOrigin::Signed(who.clone());
+	let subs = create_sub_accounts::<T>(who, s)?;
+
+	Identity::<T>::set_subs(who_origin.into(), subs.clone())?;
+
+	Ok(subs)
+}
+
+// This creates an `IdentityInfo` object with `num_fields` extra fields.
+// All data is pre-populated with some arbitrary bytes.
+fn create_identity_info<T: Config>(num_fields: u32) -> IdentityInfo<T::MaxAdditionalFields> {
+	let data = Data::Raw(vec![0; 32].try_into().unwrap());
+
+	IdentityInfo {
+		additional: vec![(data.clone(), data.clone()); num_fields as usize].try_into().unwrap(),
+		display: data.clone(),
+		legal: data.clone(),
+		web: data.clone(),
+		riot: data.clone(),
+		email: data.clone(),
+		pgp_fingerprint: Some([0; 20]),
+		image: data.clone(),
+		twitter: data,
+	}
+}
+
+benchmarks! {
+	add_registrar {
+		let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::<T>(r)?;
+		ensure!(Registrars::<T>::get().len() as u32 == r, "Registrars not set up correctly.");
+		let origin = T::RegistrarOrigin::successful_origin();
+		let account = T::Lookup::unlookup(account("registrar", r + 1, SEED));
+	}: _<T::RuntimeOrigin>(origin, account)
+	verify {
+		ensure!(Registrars::<T>::get().len() as u32 == r + 1, "Registrars not added.");
+	}
+
+	set_identity {
+		let r in 1 .. T::MaxRegistrars::get() => add_registrars::<T>(r)?;
+		let x in 0 .. T::MaxAdditionalFields::get();
+		let caller = {
+			// The target user
+			let caller: T::AccountId = whitelisted_caller();
+			let caller_lookup = T::Lookup::unlookup(caller.clone());
+			let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into();
+			let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+			// Add an initial identity
+			let initial_info = create_identity_info::<T>(1);
+			Identity::<T>::set_identity(caller_origin.clone(), Box::new(initial_info.clone()))?;
+
+			// User requests judgement from all the registrars, and they approve
+			for i in 0..r {
+				let registrar: T::AccountId = account("registrar", i, SEED);
+				let registrar_lookup = T::Lookup::unlookup(registrar.clone());
+				let balance_to_use =  T::Currency::minimum_balance() * 10u32.into();
+				let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
+
+				Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;
+				Identity::<T>::provide_judgement(
+					RawOrigin::Signed(registrar).into(),
+					i,
+					caller_lookup.clone(),
+					Judgement::Reasonable,
+					T::Hashing::hash_of(&initial_info),
+				)?;
+			}
+			caller
+		};
+	}: _(RawOrigin::Signed(caller.clone()), Box::new(create_identity_info::<T>(x)))
+	verify {
+		assert_last_event::<T>(Event::<T>::IdentitySet { who: caller }.into());
+	}
+
+	// We need to split `set_subs` into two benchmarks to accurately isolate the potential
+	// writes caused by new or old sub accounts. The actual weight should simply be
+	// the sum of these two weights.
+	set_subs_new {
+		let caller: T::AccountId = whitelisted_caller();
+		// Create a new subs vec with s sub accounts
+		let s in 0 .. T::MaxSubAccounts::get() => ();
+		let subs = create_sub_accounts::<T>(&caller, s)?;
+		ensure!(SubsOf::<T>::get(&caller).1.len() == 0, "Caller already has subs");
+	}: set_subs(RawOrigin::Signed(caller.clone()), subs)
+	verify {
+		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s, "Subs not added");
+	}
+
+	set_subs_old {
+		let caller: T::AccountId = whitelisted_caller();
+		// Give them p many previous sub accounts.
+		let p in 0 .. T::MaxSubAccounts::get() => {
+			let _ = add_sub_accounts::<T>(&caller, p)?;
+		};
+		// Remove all subs.
+		let subs = create_sub_accounts::<T>(&caller, 0)?;
+		ensure!(
+			SubsOf::<T>::get(&caller).1.len() as u32 == p,
+			"Caller does have subs",
+		);
+	}: set_subs(RawOrigin::Signed(caller.clone()), subs)
+	verify {
+		ensure!(SubsOf::<T>::get(&caller).1.len() == 0, "Subs not removed");
+	}
+
+	clear_identity {
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
+		let caller_lookup = <T::Lookup as StaticLookup>::unlookup(caller.clone());
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() => add_registrars::<T>(r)?;
+		let s in 0 .. T::MaxSubAccounts::get() => {
+			// Give them s many sub accounts
+			let caller: T::AccountId = whitelisted_caller();
+			let _ = add_sub_accounts::<T>(&caller, s)?;
+		};
+		let x in 0 .. T::MaxAdditionalFields::get();
+
+		// Create their main identity with x additional fields
+		let info = create_identity_info::<T>(x);
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
+		Identity::<T>::set_identity(caller_origin.clone(), Box::new(info.clone()))?;
+
+		// User requests judgement from all the registrars, and they approve
+		for i in 0..r {
+			let registrar: T::AccountId = account("registrar", i, SEED);
+			let balance_to_use =  T::Currency::minimum_balance() * 10u32.into();
+			let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
+
+			Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;
+			Identity::<T>::provide_judgement(
+				RawOrigin::Signed(registrar).into(),
+				i,
+				caller_lookup.clone(),
+				Judgement::Reasonable,
+				T::Hashing::hash_of(&info),
+			)?;
+		}
+		ensure!(IdentityOf::<T>::contains_key(&caller), "Identity does not exist.");
+	}: _(RawOrigin::Signed(caller.clone()))
+	verify {
+		ensure!(!IdentityOf::<T>::contains_key(&caller), "Identity not cleared.");
+	}
+
+	request_judgement {
+		let caller: T::AccountId = whitelisted_caller();
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() => add_registrars::<T>(r)?;
+		let x in 0 .. T::MaxAdditionalFields::get() => {
+			// Create their main identity with x additional fields
+			let info = create_identity_info::<T>(x);
+			let caller: T::AccountId = whitelisted_caller();
+			let caller_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller));
+			Identity::<T>::set_identity(caller_origin, Box::new(info))?;
+		};
+	}: _(RawOrigin::Signed(caller.clone()), r - 1, 10u32.into())
+	verify {
+		assert_last_event::<T>(Event::<T>::JudgementRequested { who: caller, registrar_index: r-1 }.into());
+	}
+
+	cancel_request {
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() => add_registrars::<T>(r)?;
+		let x in 0 .. T::MaxAdditionalFields::get() => {
+			// Create their main identity with x additional fields
+			let info = create_identity_info::<T>(x);
+			let caller: T::AccountId = whitelisted_caller();
+			let caller_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller));
+			Identity::<T>::set_identity(caller_origin, Box::new(info))?;
+		};
+
+		Identity::<T>::request_judgement(caller_origin, r - 1, 10u32.into())?;
+	}: _(RawOrigin::Signed(caller.clone()), r - 1)
+	verify {
+		assert_last_event::<T>(Event::<T>::JudgementUnrequested { who: caller, registrar_index: r-1 }.into());
+	}
+
+	set_fee {
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_lookup = T::Lookup::unlookup(caller.clone());
+
+		let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::<T>(r)?;
+
+		let registrar_origin = T::RegistrarOrigin::successful_origin();
+		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().fee == 0u32.into(), "Fee already set.");
+	}: _(RawOrigin::Signed(caller), r, 100u32.into())
+	verify {
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().fee == 100u32.into(), "Fee not changed.");
+	}
+
+	set_account_id {
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_lookup = T::Lookup::unlookup(caller.clone());
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::<T>(r)?;
+
+		let registrar_origin = T::RegistrarOrigin::successful_origin();
+		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().account == caller, "id not set.");
+		let new_account = T::Lookup::unlookup(account("new", 0, SEED));
+	}: _(RawOrigin::Signed(caller), r, new_account)
+	verify {
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().account == account("new", 0, SEED), "id not changed.");
+	}
+
+	set_fields {
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_lookup = T::Lookup::unlookup(caller.clone());
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::<T>(r)?;
+
+		let registrar_origin = T::RegistrarOrigin::successful_origin();
+		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
+		let fields = IdentityFields(
+			IdentityField::Display | IdentityField::Legal | IdentityField::Web | IdentityField::Riot
+			| IdentityField::Email | IdentityField::PgpFingerprint | IdentityField::Image | IdentityField::Twitter
+		);
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().fields == Default::default(), "fields already set.");
+	}: _(RawOrigin::Signed(caller), r, fields)
+	verify {
+		let registrars = Registrars::<T>::get();
+		ensure!(registrars[r as usize].as_ref().unwrap().fields != Default::default(), "fields not set.");
+	}
+
+	provide_judgement {
+		// The user
+		let user: T::AccountId = account("user", r, SEED);
+		let user_origin = <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(user.clone()));
+		let user_lookup = <T::Lookup as StaticLookup>::unlookup(user.clone());
+		let _ = T::Currency::make_free_balance_be(&user, BalanceOf::<T>::max_value());
+
+		let caller: T::AccountId = whitelisted_caller();
+		let caller_lookup = T::Lookup::unlookup(caller.clone());
+		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
+
+		let r in 1 .. T::MaxRegistrars::get() - 1 => add_registrars::<T>(r)?;
+		let x in 0 .. T::MaxAdditionalFields::get();
+
+		let info = create_identity_info::<T>(x);
+		let info_hash = T::Hashing::hash_of(&info);
+		Identity::<T>::set_identity(user_origin.clone(), Box::new(info))?;
+
+		let registrar_origin = T::RegistrarOrigin::successful_origin();
+		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
+		Identity::<T>::request_judgement(user_origin, r, 10u32.into())?;
+	}: _(RawOrigin::Signed(caller), r, user_lookup, Judgement::Reasonable, info_hash)
+	verify {
+		assert_last_event::<T>(Event::<T>::JudgementGiven { target: user, registrar_index: r }.into())
+	}
+
+	kill_identity {
+		let r in 1 .. T::MaxRegistrars::get() => add_registrars::<T>(r)?;
+		let s in 0 .. T::MaxSubAccounts::get();
+		let x in 0 .. T::MaxAdditionalFields::get();
+
+		let target: T::AccountId = account("target", 0, SEED);
+		let target_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(target.clone()).into();
+		let target_lookup = T::Lookup::unlookup(target.clone());
+		let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
+
+		let info = create_identity_info::<T>(x);
+		Identity::<T>::set_identity(target_origin.clone(), Box::new(info.clone()))?;
+		let _ = add_sub_accounts::<T>(&target, s)?;
+
+		// User requests judgement from all the registrars, and they approve
+		for i in 0..r {
+			let registrar: T::AccountId = account("registrar", i, SEED);
+			let balance_to_use =  T::Currency::minimum_balance() * 10u32.into();
+			let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
+
+			Identity::<T>::request_judgement(target_origin.clone(), i, 10u32.into())?;
+			Identity::<T>::provide_judgement(
+				RawOrigin::Signed(registrar).into(),
+				i,
+				target_lookup.clone(),
+				Judgement::Reasonable,
+				T::Hashing::hash_of(&info),
+			)?;
+		}
+		ensure!(IdentityOf::<T>::contains_key(&target), "Identity not set");
+		let origin = T::ForceOrigin::successful_origin();
+	}: _<T::RuntimeOrigin>(origin, target_lookup)
+	verify {
+		ensure!(!IdentityOf::<T>::contains_key(&target), "Identity not removed");
+	}
+
+	add_sub {
+		let s in 0 .. T::MaxSubAccounts::get() - 1;
+
+		let caller: T::AccountId = whitelisted_caller();
+		let _ = add_sub_accounts::<T>(&caller, s)?;
+		let sub = account("new_sub", 0, SEED);
+		let data = Data::Raw(vec![0; 32].try_into().unwrap());
+		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s, "Subs not set.");
+	}: _(RawOrigin::Signed(caller.clone()), T::Lookup::unlookup(sub), data)
+	verify {
+		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s + 1, "Subs not added.");
+	}
+
+	rename_sub {
+		let s in 1 .. T::MaxSubAccounts::get();
+
+		let caller: T::AccountId = whitelisted_caller();
+		let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);
+		let data = Data::Raw(vec![1; 32].try_into().unwrap());
+		ensure!(SuperOf::<T>::get(&sub).unwrap().1 != data, "data already set");
+	}: _(RawOrigin::Signed(caller), T::Lookup::unlookup(sub.clone()), data.clone())
+	verify {
+		ensure!(SuperOf::<T>::get(&sub).unwrap().1 == data, "data not set");
+	}
+
+	remove_sub {
+		let s in 1 .. T::MaxSubAccounts::get();
+
+		let caller: T::AccountId = whitelisted_caller();
+		let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);
+		ensure!(SuperOf::<T>::contains_key(&sub), "Sub doesn't exists");
+	}: _(RawOrigin::Signed(caller), T::Lookup::unlookup(sub.clone()))
+	verify {
+		ensure!(!SuperOf::<T>::contains_key(&sub), "Sub not removed");
+	}
+
+	quit_sub {
+		let s in 0 .. T::MaxSubAccounts::get() - 1;
+
+		let caller: T::AccountId = whitelisted_caller();
+		let sup = account("super", 0, SEED);
+		let _ = add_sub_accounts::<T>(&sup, s)?;
+		let sup_origin = RawOrigin::Signed(sup).into();
+		Identity::<T>::add_sub(sup_origin, T::Lookup::unlookup(caller.clone()), Data::Raw(vec![0; 32].try_into().unwrap()))?;
+		ensure!(SuperOf::<T>::contains_key(&caller), "Sub doesn't exists");
+	}: _(RawOrigin::Signed(caller.clone()))
+	verify {
+		ensure!(!SuperOf::<T>::contains_key(&caller), "Sub not removed");
+	}
+
+	impl_benchmark_test_suite!(Identity, crate::tests::new_test_ext(), crate::tests::Test);
+}
addedpallets/identity/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/src/lib.rs
@@ -0,0 +1,1030 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! # Identity Pallet
+//!
+//! - [`Config`]
+//! - [`Call`]
+//!
+//! ## Overview
+//!
+//! A federated naming system, allowing for multiple registrars to be added from a specified origin.
+//! Registrars can set a fee to provide identity-verification service. Anyone can put forth a
+//! proposed identity for a fixed deposit and ask for review by any number of registrars (paying
+//! each of their fees). Registrar judgements are given as an `enum`, allowing for sophisticated,
+//! multi-tier opinions.
+//!
+//! Some judgements are identified as *sticky*, which means they cannot be removed except by
+//! complete removal of the identity, or by the registrar. Judgements are allowed to represent a
+//! portion of funds that have been reserved for the registrar.
+//!
+//! A super-user can remove accounts and in doing so, slash the deposit.
+//!
+//! All accounts may also have a limited number of sub-accounts which may be specified by the owner;
+//! by definition, these have equivalent ownership and each has an individual name.
+//!
+//! The number of registrars should be limited, and the deposit made sufficiently large, to ensure
+//! no state-bloat attack is viable.
+//!
+//! ## Interface
+//!
+//! ### Dispatchable Functions
+//!
+//! #### For general users
+//! * `set_identity` - Set the associated identity of an account; a small deposit is reserved if not
+//!   already taken.
+//! * `clear_identity` - Remove an account's associated identity; the deposit is returned.
+//! * `request_judgement` - Request a judgement from a registrar, paying a fee.
+//! * `cancel_request` - Cancel the previous request for a judgement.
+//!
+//! #### For general users with sub-identities
+//! * `set_subs` - Set the sub-accounts of an identity.
+//! * `add_sub` - Add a sub-identity to an identity.
+//! * `remove_sub` - Remove a sub-identity of an identity.
+//! * `rename_sub` - Rename a sub-identity of an identity.
+//! * `quit_sub` - Remove a sub-identity of an identity (called by the sub-identity).
+//!
+//! #### For registrars
+//! * `set_fee` - Set the fee required to be paid for a judgement to be given by the registrar.
+//! * `set_fields` - Set the fields that a registrar cares about in their judgements.
+//! * `provide_judgement` - Provide a judgement to an identity.
+//!
+//! #### For super-users
+//! * `add_registrar` - Add a new registrar to the system.
+//! * `kill_identity` - Forcibly remove the associated identity; the deposit is lost.
+//!
+//! [`Call`]: ./enum.Call.html
+//! [`Config`]: ./trait.Config.html
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+mod benchmarking;
+#[cfg(test)]
+mod tests;
+mod types;
+pub mod weights;
+
+use frame_support::traits::{BalanceStatus, Currency, OnUnbalanced, ReservableCurrency};
+use sp_runtime::traits::{AppendZerosInput, Hash, Saturating, StaticLookup, Zero};
+use sp_std::prelude::*;
+pub use weights::WeightInfo;
+
+pub use pallet::*;
+pub use types::{
+	Data, IdentityField, IdentityFields, IdentityInfo, Judgement, RegistrarIndex, RegistrarInfo,
+	Registration,
+};
+
+pub type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
+	<T as frame_system::Config>::AccountId,
+>>::NegativeImbalance;
+type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use super::*;
+	use frame_support::pallet_prelude::*;
+	use frame_system::pallet_prelude::*;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		/// The overarching event type.
+		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+
+		/// The currency trait.
+		type Currency: ReservableCurrency<Self::AccountId>;
+
+		/// The amount held on deposit for a registered identity
+		#[pallet::constant]
+		type BasicDeposit: Get<BalanceOf<Self>>;
+
+		/// The amount held on deposit per additional field for a registered identity.
+		#[pallet::constant]
+		type FieldDeposit: Get<BalanceOf<Self>>;
+
+		/// The amount held on deposit for a registered subaccount. This should account for the fact
+		/// that one storage item's value will increase by the size of an account ID, and there will
+		/// be another trie item whose value is the size of an account ID plus 32 bytes.
+		#[pallet::constant]
+		type SubAccountDeposit: Get<BalanceOf<Self>>;
+
+		/// The maximum number of sub-accounts allowed per identified account.
+		#[pallet::constant]
+		type MaxSubAccounts: Get<u32>;
+
+		/// Maximum number of additional fields that may be stored in an ID. Needed to bound the I/O
+		/// required to access an identity, but can be pretty high.
+		#[pallet::constant]
+		type MaxAdditionalFields: Get<u32>;
+
+		/// Maxmimum number of registrars allowed in the system. Needed to bound the complexity
+		/// of, e.g., updating judgements.
+		#[pallet::constant]
+		type MaxRegistrars: Get<u32>;
+
+		/// What to do with slashed funds.
+		type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;
+
+		/// The origin which may forcibly set or remove a name. Root can always do this.
+		type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
+
+		/// The origin which may add or remove registrars. Root can always do this.
+		type RegistrarOrigin: EnsureOrigin<Self::RuntimeOrigin>;
+
+		/// Weight information for extrinsics in this pallet.
+		type WeightInfo: WeightInfo;
+	}
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	/// Information that is pertinent to identify the entity behind an account.
+	///
+	/// TWOX-NOTE: OK ― `AccountId` is a secure hash.
+	#[pallet::storage]
+	#[pallet::getter(fn identity)]
+	pub type IdentityOf<T: Config> = StorageMap<
+		_,
+		Twox64Concat,
+		T::AccountId,
+		Registration<BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields>,
+		OptionQuery,
+	>;
+
+	/// The super-identity of an alternative "sub" identity together with its name, within that
+	/// context. If the account is not some other account's sub-identity, then just `None`.
+	#[pallet::storage]
+	#[pallet::getter(fn super_of)]
+	pub(super) type SuperOf<T: Config> =
+		StorageMap<_, Blake2_128Concat, T::AccountId, (T::AccountId, Data), OptionQuery>;
+
+	/// Alternative "sub" identities of this account.
+	///
+	/// The first item is the deposit, the second is a vector of the accounts.
+	///
+	/// TWOX-NOTE: OK ― `AccountId` is a secure hash.
+	#[pallet::storage]
+	#[pallet::getter(fn subs_of)]
+	pub(super) type SubsOf<T: Config> = StorageMap<
+		_,
+		Twox64Concat,
+		T::AccountId,
+		(BalanceOf<T>, BoundedVec<T::AccountId, T::MaxSubAccounts>),
+		ValueQuery,
+	>;
+
+	/// The set of registrars. Not expected to get very big as can only be added through a
+	/// special origin (likely a council motion).
+	///
+	/// The index into this can be cast to `RegistrarIndex` to get a valid value.
+	#[pallet::storage]
+	#[pallet::getter(fn registrars)]
+	pub(super) type Registrars<T: Config> = StorageValue<
+		_,
+		BoundedVec<Option<RegistrarInfo<BalanceOf<T>, T::AccountId>>, T::MaxRegistrars>,
+		ValueQuery,
+	>;
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// Too many subs-accounts.
+		TooManySubAccounts,
+		/// Account isn't found.
+		NotFound,
+		/// Account isn't named.
+		NotNamed,
+		/// Empty index.
+		EmptyIndex,
+		/// Fee is changed.
+		FeeChanged,
+		/// No identity found.
+		NoIdentity,
+		/// Sticky judgement.
+		StickyJudgement,
+		/// Judgement given.
+		JudgementGiven,
+		/// Invalid judgement.
+		InvalidJudgement,
+		/// The index is invalid.
+		InvalidIndex,
+		/// The target is invalid.
+		InvalidTarget,
+		/// Too many additional fields.
+		TooManyFields,
+		/// Maximum amount of registrars reached. Cannot add any more.
+		TooManyRegistrars,
+		/// Account ID is already named.
+		AlreadyClaimed,
+		/// Sender is not a sub-account.
+		NotSub,
+		/// Sub-account isn't owned by sender.
+		NotOwned,
+		/// The provided judgement was for a different identity.
+		JudgementForDifferentIdentity,
+		/// Error that occurs when there is an issue paying for judgement.
+		JudgementPaymentFailed,
+	}
+
+	#[pallet::event]
+	#[pallet::generate_deposit(pub(super) fn deposit_event)]
+	pub enum Event<T: Config> {
+		/// A name was set or reset (which will remove all judgements).
+		IdentitySet { who: T::AccountId },
+		/// A name was cleared, and the given balance returned.
+		IdentityCleared { who: T::AccountId, deposit: BalanceOf<T> },
+		/// A name was removed and the given balance slashed.
+		IdentityKilled { who: T::AccountId, deposit: BalanceOf<T> },
+		/// A judgement was asked from a registrar.
+		JudgementRequested { who: T::AccountId, registrar_index: RegistrarIndex },
+		/// A judgement request was retracted.
+		JudgementUnrequested { who: T::AccountId, registrar_index: RegistrarIndex },
+		/// A judgement was given by a registrar.
+		JudgementGiven { target: T::AccountId, registrar_index: RegistrarIndex },
+		/// A registrar was added.
+		RegistrarAdded { registrar_index: RegistrarIndex },
+		/// A sub-identity was added to an identity and the deposit paid.
+		SubIdentityAdded { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
+		/// A sub-identity was removed from an identity and the deposit freed.
+		SubIdentityRemoved { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
+		/// A sub-identity was cleared, and the given deposit repatriated from the
+		/// main identity account to the sub-identity account.
+		SubIdentityRevoked { sub: T::AccountId, main: T::AccountId, deposit: BalanceOf<T> },
+	}
+
+	#[pallet::call]
+	/// Identity pallet declaration.
+	impl<T: Config> Pallet<T> {
+		/// Add a registrar to the system.
+		///
+		/// The dispatch origin for this call must be `T::RegistrarOrigin`.
+		///
+		/// - `account`: the account of the registrar.
+		///
+		/// Emits `RegistrarAdded` if successful.
+		///
+		/// # <weight>
+		/// - `O(R)` where `R` registrar-count (governance-bounded and code-bounded).
+		/// - One storage mutation (codec `O(R)`).
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(0)]
+		#[pallet::weight(T::WeightInfo::add_registrar(T::MaxRegistrars::get()))]
+		pub fn add_registrar(
+			origin: OriginFor<T>,
+			account: AccountIdLookupOf<T>,
+		) -> DispatchResultWithPostInfo {
+			T::RegistrarOrigin::ensure_origin(origin)?;
+			let account = T::Lookup::lookup(account)?;
+
+			let (i, registrar_count) = <Registrars<T>>::try_mutate(
+				|registrars| -> Result<(RegistrarIndex, usize), DispatchError> {
+					registrars
+						.try_push(Some(RegistrarInfo {
+							account,
+							fee: Zero::zero(),
+							fields: Default::default(),
+						}))
+						.map_err(|_| Error::<T>::TooManyRegistrars)?;
+					Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len()))
+				},
+			)?;
+
+			Self::deposit_event(Event::RegistrarAdded { registrar_index: i });
+
+			Ok(Some(T::WeightInfo::add_registrar(registrar_count as u32)).into())
+		}
+
+		/// Set an account's identity information and reserve the appropriate deposit.
+		///
+		/// If the account already has identity information, the deposit is taken as part payment
+		/// for the new deposit.
+		///
+		/// The dispatch origin for this call must be _Signed_.
+		///
+		/// - `info`: The identity information.
+		///
+		/// Emits `IdentitySet` if successful.
+		///
+		/// # <weight>
+		/// - `O(X + X' + R)`
+		///   - where `X` additional-field-count (deposit-bounded and code-bounded)
+		///   - where `R` judgements-count (registrar-count-bounded)
+		/// - One balance reserve operation.
+		/// - One storage mutation (codec-read `O(X' + R)`, codec-write `O(X + R)`).
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(1)]
+		#[pallet::weight( T::WeightInfo::set_identity(
+			T::MaxRegistrars::get(), // R
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn set_identity(
+			origin: OriginFor<T>,
+			info: Box<IdentityInfo<T::MaxAdditionalFields>>,
+		) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+			let extra_fields = info.additional.len() as u32;
+			ensure!(extra_fields <= T::MaxAdditionalFields::get(), Error::<T>::TooManyFields);
+			let fd = <BalanceOf<T>>::from(extra_fields) * T::FieldDeposit::get();
+
+			let mut id = match <IdentityOf<T>>::get(&sender) {
+				Some(mut id) => {
+					// Only keep non-positive judgements.
+					id.judgements.retain(|j| j.1.is_sticky());
+					id.info = *info;
+					id
+				},
+				None => Registration {
+					info: *info,
+					judgements: BoundedVec::default(),
+					deposit: Zero::zero(),
+				},
+			};
+
+			let old_deposit = id.deposit;
+			id.deposit = T::BasicDeposit::get() + fd;
+			if id.deposit > old_deposit {
+				T::Currency::reserve(&sender, id.deposit - old_deposit)?;
+			}
+			if old_deposit > id.deposit {
+				let err_amount = T::Currency::unreserve(&sender, old_deposit - id.deposit);
+				debug_assert!(err_amount.is_zero());
+			}
+
+			let judgements = id.judgements.len();
+			<IdentityOf<T>>::insert(&sender, id);
+			Self::deposit_event(Event::IdentitySet { who: sender });
+
+			Ok(Some(T::WeightInfo::set_identity(
+				judgements as u32, // R
+				extra_fields,      // X
+			))
+			.into())
+		}
+
+		/// Set the sub-accounts of the sender.
+		///
+		/// Payment: Any aggregate balance reserved by previous `set_subs` calls will be returned
+		/// and an amount `SubAccountDeposit` will be reserved for each item in `subs`.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// identity.
+		///
+		/// - `subs`: The identity's (new) sub-accounts.
+		///
+		/// # <weight>
+		/// - `O(P + S)`
+		///   - where `P` old-subs-count (hard- and deposit-bounded).
+		///   - where `S` subs-count (hard- and deposit-bounded).
+		/// - At most one balance operations.
+		/// - DB:
+		///   - `P + S` storage mutations (codec complexity `O(1)`)
+		///   - One storage read (codec complexity `O(P)`).
+		///   - One storage write (codec complexity `O(S)`).
+		///   - One storage-exists (`IdentityOf::contains_key`).
+		/// # </weight>
+		// TODO: This whole extrinsic screams "not optimized". For example we could
+		// filter any overlap between new and old subs, and avoid reading/writing
+		// to those values... We could also ideally avoid needing to write to
+		// N storage items for N sub accounts. Right now the weight on this function
+		// is a large overestimate due to the fact that it could potentially write
+		// to 2 x T::MaxSubAccounts::get().
+		#[pallet::call_index(2)]
+		#[pallet::weight(T::WeightInfo::set_subs_old(T::MaxSubAccounts::get()) // P: Assume max sub accounts removed.
+			.saturating_add(T::WeightInfo::set_subs_new(subs.len() as u32)) // S: Assume all subs are new.
+		)]
+		pub fn set_subs(
+			origin: OriginFor<T>,
+			subs: Vec<(T::AccountId, Data)>,
+		) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+			ensure!(<IdentityOf<T>>::contains_key(&sender), Error::<T>::NotFound);
+			ensure!(
+				subs.len() <= T::MaxSubAccounts::get() as usize,
+				Error::<T>::TooManySubAccounts
+			);
+
+			let (old_deposit, old_ids) = <SubsOf<T>>::get(&sender);
+			let new_deposit = T::SubAccountDeposit::get() * <BalanceOf<T>>::from(subs.len() as u32);
+
+			let not_other_sub =
+				subs.iter().filter_map(|i| SuperOf::<T>::get(&i.0)).all(|i| i.0 == sender);
+			ensure!(not_other_sub, Error::<T>::AlreadyClaimed);
+
+			if old_deposit < new_deposit {
+				T::Currency::reserve(&sender, new_deposit - old_deposit)?;
+			} else if old_deposit > new_deposit {
+				let err_amount = T::Currency::unreserve(&sender, old_deposit - new_deposit);
+				debug_assert!(err_amount.is_zero());
+			}
+			// do nothing if they're equal.
+
+			for s in old_ids.iter() {
+				<SuperOf<T>>::remove(s);
+			}
+			let mut ids = BoundedVec::<T::AccountId, T::MaxSubAccounts>::default();
+			for (id, name) in subs {
+				<SuperOf<T>>::insert(&id, (sender.clone(), name));
+				ids.try_push(id).expect("subs length is less than T::MaxSubAccounts; qed");
+			}
+			let new_subs = ids.len();
+
+			if ids.is_empty() {
+				<SubsOf<T>>::remove(&sender);
+			} else {
+				<SubsOf<T>>::insert(&sender, (new_deposit, ids));
+			}
+
+			Ok(Some(
+				T::WeightInfo::set_subs_old(old_ids.len() as u32) // P: Real number of old accounts removed.
+					// S: New subs added
+					.saturating_add(T::WeightInfo::set_subs_new(new_subs as u32)),
+			)
+			.into())
+		}
+
+		/// Clear an account's identity info and all sub-accounts and return all deposits.
+		///
+		/// Payment: All reserved balances on the account are returned.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// identity.
+		///
+		/// Emits `IdentityCleared` if successful.
+		///
+		/// # <weight>
+		/// - `O(R + S + X)`
+		///   - where `R` registrar-count (governance-bounded).
+		///   - where `S` subs-count (hard- and deposit-bounded).
+		///   - where `X` additional-field-count (deposit-bounded and code-bounded).
+		/// - One balance-unreserve operation.
+		/// - `2` storage reads and `S + 2` storage deletions.
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(3)]
+		#[pallet::weight(T::WeightInfo::clear_identity(
+			T::MaxRegistrars::get(), // R
+			T::MaxSubAccounts::get(), // S
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn clear_identity(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+
+			let (subs_deposit, sub_ids) = <SubsOf<T>>::take(&sender);
+			let id = <IdentityOf<T>>::take(&sender).ok_or(Error::<T>::NotNamed)?;
+			let deposit = id.total_deposit() + subs_deposit;
+			for sub in sub_ids.iter() {
+				<SuperOf<T>>::remove(sub);
+			}
+
+			let err_amount = T::Currency::unreserve(&sender, deposit);
+			debug_assert!(err_amount.is_zero());
+
+			Self::deposit_event(Event::IdentityCleared { who: sender, deposit });
+
+			Ok(Some(T::WeightInfo::clear_identity(
+				id.judgements.len() as u32,      // R
+				sub_ids.len() as u32,            // S
+				id.info.additional.len() as u32, // X
+			))
+			.into())
+		}
+
+		/// Request a judgement from a registrar.
+		///
+		/// Payment: At most `max_fee` will be reserved for payment to the registrar if judgement
+		/// given.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a
+		/// registered identity.
+		///
+		/// - `reg_index`: The index of the registrar whose judgement is requested.
+		/// - `max_fee`: The maximum fee that may be paid. This should just be auto-populated as:
+		///
+		/// ```nocompile
+		/// Self::registrars().get(reg_index).unwrap().fee
+		/// ```
+		///
+		/// Emits `JudgementRequested` if successful.
+		///
+		/// # <weight>
+		/// - `O(R + X)`.
+		/// - One balance-reserve operation.
+		/// - Storage: 1 read `O(R)`, 1 mutate `O(X + R)`.
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(4)]
+		#[pallet::weight(T::WeightInfo::request_judgement(
+			T::MaxRegistrars::get(), // R
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn request_judgement(
+			origin: OriginFor<T>,
+			#[pallet::compact] reg_index: RegistrarIndex,
+			#[pallet::compact] max_fee: BalanceOf<T>,
+		) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+			let registrars = <Registrars<T>>::get();
+			let registrar = registrars
+				.get(reg_index as usize)
+				.and_then(Option::as_ref)
+				.ok_or(Error::<T>::EmptyIndex)?;
+			ensure!(max_fee >= registrar.fee, Error::<T>::FeeChanged);
+			let mut id = <IdentityOf<T>>::get(&sender).ok_or(Error::<T>::NoIdentity)?;
+
+			let item = (reg_index, Judgement::FeePaid(registrar.fee));
+			match id.judgements.binary_search_by_key(&reg_index, |x| x.0) {
+				Ok(i) =>
+					if id.judgements[i].1.is_sticky() {
+						return Err(Error::<T>::StickyJudgement.into())
+					} else {
+						id.judgements[i] = item
+					},
+				Err(i) =>
+					id.judgements.try_insert(i, item).map_err(|_| Error::<T>::TooManyRegistrars)?,
+			}
+
+			T::Currency::reserve(&sender, registrar.fee)?;
+
+			let judgements = id.judgements.len();
+			let extra_fields = id.info.additional.len();
+			<IdentityOf<T>>::insert(&sender, id);
+
+			Self::deposit_event(Event::JudgementRequested {
+				who: sender,
+				registrar_index: reg_index,
+			});
+
+			Ok(Some(T::WeightInfo::request_judgement(judgements as u32, extra_fields as u32))
+				.into())
+		}
+
+		/// Cancel a previous request.
+		///
+		/// Payment: A previously reserved deposit is returned on success.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a
+		/// registered identity.
+		///
+		/// - `reg_index`: The index of the registrar whose judgement is no longer requested.
+		///
+		/// Emits `JudgementUnrequested` if successful.
+		///
+		/// # <weight>
+		/// - `O(R + X)`.
+		/// - One balance-reserve operation.
+		/// - One storage mutation `O(R + X)`.
+		/// - One event
+		/// # </weight>
+		#[pallet::call_index(5)]
+		#[pallet::weight(T::WeightInfo::cancel_request(
+			T::MaxRegistrars::get(), // R
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn cancel_request(
+			origin: OriginFor<T>,
+			reg_index: RegistrarIndex,
+		) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+			let mut id = <IdentityOf<T>>::get(&sender).ok_or(Error::<T>::NoIdentity)?;
+
+			let pos = id
+				.judgements
+				.binary_search_by_key(&reg_index, |x| x.0)
+				.map_err(|_| Error::<T>::NotFound)?;
+			let fee = if let Judgement::FeePaid(fee) = id.judgements.remove(pos).1 {
+				fee
+			} else {
+				return Err(Error::<T>::JudgementGiven.into())
+			};
+
+			let err_amount = T::Currency::unreserve(&sender, fee);
+			debug_assert!(err_amount.is_zero());
+			let judgements = id.judgements.len();
+			let extra_fields = id.info.additional.len();
+			<IdentityOf<T>>::insert(&sender, id);
+
+			Self::deposit_event(Event::JudgementUnrequested {
+				who: sender,
+				registrar_index: reg_index,
+			});
+
+			Ok(Some(T::WeightInfo::cancel_request(judgements as u32, extra_fields as u32)).into())
+		}
+
+		/// Set the fee required for a judgement to be requested from a registrar.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
+		/// of the registrar whose index is `index`.
+		///
+		/// - `index`: the index of the registrar whose fee is to be set.
+		/// - `fee`: the new fee.
+		///
+		/// # <weight>
+		/// - `O(R)`.
+		/// - One storage mutation `O(R)`.
+		/// - Benchmark: 7.315 + R * 0.329 µs (min squares analysis)
+		/// # </weight>
+		#[pallet::call_index(6)]
+		#[pallet::weight(T::WeightInfo::set_fee(T::MaxRegistrars::get()))] // R
+		pub fn set_fee(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: RegistrarIndex,
+			#[pallet::compact] fee: BalanceOf<T>,
+		) -> DispatchResultWithPostInfo {
+			let who = ensure_signed(origin)?;
+
+			let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {
+				rs.get_mut(index as usize)
+					.and_then(|x| x.as_mut())
+					.and_then(|r| {
+						if r.account == who {
+							r.fee = fee;
+							Some(())
+						} else {
+							None
+						}
+					})
+					.ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
+				Ok(rs.len())
+			})?;
+			Ok(Some(T::WeightInfo::set_fee(registrars as u32)).into()) // R
+		}
+
+		/// Change the account associated with a registrar.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
+		/// of the registrar whose index is `index`.
+		///
+		/// - `index`: the index of the registrar whose fee is to be set.
+		/// - `new`: the new account ID.
+		///
+		/// # <weight>
+		/// - `O(R)`.
+		/// - One storage mutation `O(R)`.
+		/// - Benchmark: 8.823 + R * 0.32 µs (min squares analysis)
+		/// # </weight>
+		#[pallet::call_index(7)]
+		#[pallet::weight(T::WeightInfo::set_account_id(T::MaxRegistrars::get()))] // R
+		pub fn set_account_id(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: RegistrarIndex,
+			new: AccountIdLookupOf<T>,
+		) -> DispatchResultWithPostInfo {
+			let who = ensure_signed(origin)?;
+			let new = T::Lookup::lookup(new)?;
+
+			let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {
+				rs.get_mut(index as usize)
+					.and_then(|x| x.as_mut())
+					.and_then(|r| {
+						if r.account == who {
+							r.account = new;
+							Some(())
+						} else {
+							None
+						}
+					})
+					.ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
+				Ok(rs.len())
+			})?;
+			Ok(Some(T::WeightInfo::set_account_id(registrars as u32)).into()) // R
+		}
+
+		/// Set the field information for a registrar.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
+		/// of the registrar whose index is `index`.
+		///
+		/// - `index`: the index of the registrar whose fee is to be set.
+		/// - `fields`: the fields that the registrar concerns themselves with.
+		///
+		/// # <weight>
+		/// - `O(R)`.
+		/// - One storage mutation `O(R)`.
+		/// - Benchmark: 7.464 + R * 0.325 µs (min squares analysis)
+		/// # </weight>
+		#[pallet::call_index(8)]
+		#[pallet::weight(T::WeightInfo::set_fields(T::MaxRegistrars::get()))] // R
+		pub fn set_fields(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: RegistrarIndex,
+			fields: IdentityFields,
+		) -> DispatchResultWithPostInfo {
+			let who = ensure_signed(origin)?;
+
+			let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {
+				rs.get_mut(index as usize)
+					.and_then(|x| x.as_mut())
+					.and_then(|r| {
+						if r.account == who {
+							r.fields = fields;
+							Some(())
+						} else {
+							None
+						}
+					})
+					.ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;
+				Ok(rs.len())
+			})?;
+			Ok(Some(T::WeightInfo::set_fields(
+				registrars as u32, // R
+			))
+			.into())
+		}
+
+		/// Provide a judgement for an account's identity.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must be the account
+		/// of the registrar whose index is `reg_index`.
+		///
+		/// - `reg_index`: the index of the registrar whose judgement is being made.
+		/// - `target`: the account whose identity the judgement is upon. This must be an account
+		///   with a registered identity.
+		/// - `judgement`: the judgement of the registrar of index `reg_index` about `target`.
+		/// - `identity`: The hash of the [`IdentityInfo`] for that the judgement is provided.
+		///
+		/// Emits `JudgementGiven` if successful.
+		///
+		/// # <weight>
+		/// - `O(R + X)`.
+		/// - One balance-transfer operation.
+		/// - Up to one account-lookup operation.
+		/// - Storage: 1 read `O(R)`, 1 mutate `O(R + X)`.
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(9)]
+		#[pallet::weight(T::WeightInfo::provide_judgement(
+			T::MaxRegistrars::get(), // R
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn provide_judgement(
+			origin: OriginFor<T>,
+			#[pallet::compact] reg_index: RegistrarIndex,
+			target: AccountIdLookupOf<T>,
+			judgement: Judgement<BalanceOf<T>>,
+			identity: T::Hash,
+		) -> DispatchResultWithPostInfo {
+			let sender = ensure_signed(origin)?;
+			let target = T::Lookup::lookup(target)?;
+			ensure!(!judgement.has_deposit(), Error::<T>::InvalidJudgement);
+			<Registrars<T>>::get()
+				.get(reg_index as usize)
+				.and_then(Option::as_ref)
+				.filter(|r| r.account == sender)
+				.ok_or(Error::<T>::InvalidIndex)?;
+			let mut id = <IdentityOf<T>>::get(&target).ok_or(Error::<T>::InvalidTarget)?;
+
+			if T::Hashing::hash_of(&id.info) != identity {
+				return Err(Error::<T>::JudgementForDifferentIdentity.into())
+			}
+
+			let item = (reg_index, judgement);
+			match id.judgements.binary_search_by_key(&reg_index, |x| x.0) {
+				Ok(position) => {
+					if let Judgement::FeePaid(fee) = id.judgements[position].1 {
+						T::Currency::repatriate_reserved(
+							&target,
+							&sender,
+							fee,
+							BalanceStatus::Free,
+						)
+						.map_err(|_| Error::<T>::JudgementPaymentFailed)?;
+					}
+					id.judgements[position] = item
+				},
+				Err(position) => id
+					.judgements
+					.try_insert(position, item)
+					.map_err(|_| Error::<T>::TooManyRegistrars)?,
+			}
+
+			let judgements = id.judgements.len();
+			let extra_fields = id.info.additional.len();
+			<IdentityOf<T>>::insert(&target, id);
+			Self::deposit_event(Event::JudgementGiven { target, registrar_index: reg_index });
+
+			Ok(Some(T::WeightInfo::provide_judgement(judgements as u32, extra_fields as u32))
+				.into())
+		}
+
+		/// Remove an account's identity and sub-account information and slash the deposits.
+		///
+		/// Payment: Reserved balances from `set_subs` and `set_identity` are slashed and handled by
+		/// `Slash`. Verification request deposits are not returned; they should be cancelled
+		/// manually using `cancel_request`.
+		///
+		/// The dispatch origin for this call must match `T::ForceOrigin`.
+		///
+		/// - `target`: the account whose identity the judgement is upon. This must be an account
+		///   with a registered identity.
+		///
+		/// Emits `IdentityKilled` if successful.
+		///
+		/// # <weight>
+		/// - `O(R + S + X)`.
+		/// - One balance-reserve operation.
+		/// - `S + 2` storage mutations.
+		/// - One event.
+		/// # </weight>
+		#[pallet::call_index(10)]
+		#[pallet::weight(T::WeightInfo::kill_identity(
+			T::MaxRegistrars::get(), // R
+			T::MaxSubAccounts::get(), // S
+			T::MaxAdditionalFields::get(), // X
+		))]
+		pub fn kill_identity(
+			origin: OriginFor<T>,
+			target: AccountIdLookupOf<T>,
+		) -> DispatchResultWithPostInfo {
+			T::ForceOrigin::ensure_origin(origin)?;
+
+			// Figure out who we're meant to be clearing.
+			let target = T::Lookup::lookup(target)?;
+			// Grab their deposit (and check that they have one).
+			let (subs_deposit, sub_ids) = <SubsOf<T>>::take(&target);
+			let id = <IdentityOf<T>>::take(&target).ok_or(Error::<T>::NotNamed)?;
+			let deposit = id.total_deposit() + subs_deposit;
+			for sub in sub_ids.iter() {
+				<SuperOf<T>>::remove(sub);
+			}
+			// Slash their deposit from them.
+			T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0);
+
+			Self::deposit_event(Event::IdentityKilled { who: target, deposit });
+
+			Ok(Some(T::WeightInfo::kill_identity(
+				id.judgements.len() as u32,      // R
+				sub_ids.len() as u32,            // S
+				id.info.additional.len() as u32, // X
+			))
+			.into())
+		}
+
+		/// Add the given account to the sender's subs.
+		///
+		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+		/// to the sender.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// sub identity of `sub`.
+		#[pallet::call_index(11)]
+		#[pallet::weight(T::WeightInfo::add_sub(T::MaxSubAccounts::get()))]
+		pub fn add_sub(
+			origin: OriginFor<T>,
+			sub: AccountIdLookupOf<T>,
+			data: Data,
+		) -> DispatchResult {
+			let sender = ensure_signed(origin)?;
+			let sub = T::Lookup::lookup(sub)?;
+			ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
+
+			// Check if it's already claimed as sub-identity.
+			ensure!(!SuperOf::<T>::contains_key(&sub), Error::<T>::AlreadyClaimed);
+
+			SubsOf::<T>::try_mutate(&sender, |(ref mut subs_deposit, ref mut sub_ids)| {
+				// Ensure there is space and that the deposit is paid.
+				ensure!(
+					sub_ids.len() < T::MaxSubAccounts::get() as usize,
+					Error::<T>::TooManySubAccounts
+				);
+				let deposit = T::SubAccountDeposit::get();
+				T::Currency::reserve(&sender, deposit)?;
+
+				SuperOf::<T>::insert(&sub, (sender.clone(), data));
+				sub_ids.try_push(sub.clone()).expect("sub ids length checked above; qed");
+				*subs_deposit = subs_deposit.saturating_add(deposit);
+
+				Self::deposit_event(Event::SubIdentityAdded { sub, main: sender.clone(), deposit });
+				Ok(())
+			})
+		}
+
+		/// Alter the associated name of the given sub-account.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// sub identity of `sub`.
+		#[pallet::call_index(12)]
+		#[pallet::weight(T::WeightInfo::rename_sub(T::MaxSubAccounts::get()))]
+		pub fn rename_sub(
+			origin: OriginFor<T>,
+			sub: AccountIdLookupOf<T>,
+			data: Data,
+		) -> DispatchResult {
+			let sender = ensure_signed(origin)?;
+			let sub = T::Lookup::lookup(sub)?;
+			ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
+			ensure!(SuperOf::<T>::get(&sub).map_or(false, |x| x.0 == sender), Error::<T>::NotOwned);
+			SuperOf::<T>::insert(&sub, (sender, data));
+			Ok(())
+		}
+
+		/// Remove the given account from the sender's subs.
+		///
+		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+		/// to the sender.
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// sub identity of `sub`.
+		#[pallet::call_index(13)]
+		#[pallet::weight(T::WeightInfo::remove_sub(T::MaxSubAccounts::get()))]
+		pub fn remove_sub(origin: OriginFor<T>, sub: AccountIdLookupOf<T>) -> DispatchResult {
+			let sender = ensure_signed(origin)?;
+			ensure!(IdentityOf::<T>::contains_key(&sender), Error::<T>::NoIdentity);
+			let sub = T::Lookup::lookup(sub)?;
+			let (sup, _) = SuperOf::<T>::get(&sub).ok_or(Error::<T>::NotSub)?;
+			ensure!(sup == sender, Error::<T>::NotOwned);
+			SuperOf::<T>::remove(&sub);
+			SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {
+				sub_ids.retain(|x| x != &sub);
+				let deposit = T::SubAccountDeposit::get().min(*subs_deposit);
+				*subs_deposit -= deposit;
+				let err_amount = T::Currency::unreserve(&sender, deposit);
+				debug_assert!(err_amount.is_zero());
+				Self::deposit_event(Event::SubIdentityRemoved { sub, main: sender, deposit });
+			});
+			Ok(())
+		}
+
+		/// Remove the sender as a sub-account.
+		///
+		/// Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+		/// to the sender (*not* the original depositor).
+		///
+		/// The dispatch origin for this call must be _Signed_ and the sender must have a registered
+		/// super-identity.
+		///
+		/// NOTE: This should not normally be used, but is provided in the case that the non-
+		/// controller of an account is maliciously registered as a sub-account.
+		#[pallet::call_index(14)]
+		#[pallet::weight(T::WeightInfo::quit_sub(T::MaxSubAccounts::get()))]
+		pub fn quit_sub(origin: OriginFor<T>) -> DispatchResult {
+			let sender = ensure_signed(origin)?;
+			let (sup, _) = SuperOf::<T>::take(&sender).ok_or(Error::<T>::NotSub)?;
+			SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {
+				sub_ids.retain(|x| x != &sender);
+				let deposit = T::SubAccountDeposit::get().min(*subs_deposit);
+				*subs_deposit -= deposit;
+				let _ =
+					T::Currency::repatriate_reserved(&sup, &sender, deposit, BalanceStatus::Free);
+				Self::deposit_event(Event::SubIdentityRevoked {
+					sub: sender,
+					main: sup.clone(),
+					deposit,
+				});
+			});
+			Ok(())
+		}
+	}
+}
+
+impl<T: Config> Pallet<T> {
+	/// Get the subs of an account.
+	pub fn subs(who: &T::AccountId) -> Vec<(T::AccountId, Data)> {
+		SubsOf::<T>::get(who)
+			.1
+			.into_iter()
+			.filter_map(|a| SuperOf::<T>::get(&a).map(|x| (a, x.1)))
+			.collect()
+	}
+
+	/// Check if the account has corresponding identity information by the identity field.
+	pub fn has_identity(who: &T::AccountId, fields: u64) -> bool {
+		IdentityOf::<T>::get(who)
+			.map_or(false, |registration| (registration.info.fields().0.bits() & fields) == fields)
+	}
+}
addedpallets/identity/src/tests.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/src/tests.rs
@@ -0,0 +1,643 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Tests for Identity Pallet
+
+use super::*;
+use crate as pallet_identity;
+
+use codec::{Decode, Encode};
+use frame_support::{
+	assert_noop, assert_ok, ord_parameter_types, parameter_types,
+	traits::{ConstU32, ConstU64, EitherOfDiverse},
+	BoundedVec,
+};
+use frame_system::{EnsureRoot, EnsureSignedBy};
+use sp_core::H256;
+use sp_runtime::{
+	testing::Header,
+	traits::{BadOrigin, BlakeTwo256, IdentityLookup},
+};
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+frame_support::construct_runtime!(
+	pub enum Test where
+		Block = Block,
+		NodeBlock = Block,
+		UncheckedExtrinsic = UncheckedExtrinsic,
+	{
+		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
+		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
+		Identity: pallet_identity::{Pallet, Call, Storage, Event<T>},
+	}
+);
+
+parameter_types! {
+	pub BlockWeights: frame_system::limits::BlockWeights =
+		frame_system::limits::BlockWeights::simple_max(frame_support::weights::Weight::from_ref_time(1024));
+}
+impl frame_system::Config for Test {
+	type BaseCallFilter = frame_support::traits::Everything;
+	type BlockWeights = ();
+	type BlockLength = ();
+	type RuntimeOrigin = RuntimeOrigin;
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type RuntimeCall = RuntimeCall;
+	type Hashing = BlakeTwo256;
+	type AccountId = u64;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Header = Header;
+	type RuntimeEvent = RuntimeEvent;
+	type BlockHashCount = ConstU64<250>;
+	type DbWeight = ();
+	type Version = ();
+	type PalletInfo = PalletInfo;
+	type AccountData = pallet_balances::AccountData<u64>;
+	type OnNewAccount = ();
+	type OnKilledAccount = ();
+	type SystemWeightInfo = ();
+	type SS58Prefix = ();
+	type OnSetCode = ();
+	type MaxConsumers = ConstU32<16>;
+}
+
+impl pallet_balances::Config for Test {
+	type Balance = u64;
+	type RuntimeEvent = RuntimeEvent;
+	type DustRemoval = ();
+	type ExistentialDeposit = ConstU64<1>;
+	type AccountStore = System;
+	type MaxLocks = ();
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = ();
+}
+
+parameter_types! {
+	pub const MaxAdditionalFields: u32 = 2;
+	pub const MaxRegistrars: u32 = 20;
+}
+
+ord_parameter_types! {
+	pub const One: u64 = 1;
+	pub const Two: u64 = 2;
+}
+type EnsureOneOrRoot = EitherOfDiverse<EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
+type EnsureTwoOrRoot = EitherOfDiverse<EnsureRoot<u64>, EnsureSignedBy<Two, u64>>;
+impl pallet_identity::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type Slashed = ();
+	type BasicDeposit = ConstU64<10>;
+	type FieldDeposit = ConstU64<10>;
+	type SubAccountDeposit = ConstU64<10>;
+	type MaxSubAccounts = ConstU32<2>;
+	type MaxAdditionalFields = MaxAdditionalFields;
+	type MaxRegistrars = MaxRegistrars;
+	type RegistrarOrigin = EnsureOneOrRoot;
+	type ForceOrigin = EnsureTwoOrRoot;
+	type WeightInfo = ();
+}
+
+pub fn new_test_ext() -> sp_io::TestExternalities {
+	let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
+	pallet_balances::GenesisConfig::<Test> {
+		balances: vec![(1, 10), (2, 10), (3, 10), (10, 100), (20, 100), (30, 100)],
+	}
+	.assimilate_storage(&mut t)
+	.unwrap();
+	t.into()
+}
+
+fn ten() -> IdentityInfo<MaxAdditionalFields> {
+	IdentityInfo {
+		display: Data::Raw(b"ten".to_vec().try_into().unwrap()),
+		legal: Data::Raw(b"The Right Ordinal Ten, Esq.".to_vec().try_into().unwrap()),
+		..Default::default()
+	}
+}
+
+fn twenty() -> IdentityInfo<MaxAdditionalFields> {
+	IdentityInfo {
+		display: Data::Raw(b"twenty".to_vec().try_into().unwrap()),
+		legal: Data::Raw(b"The Right Ordinal Twenty, Esq.".to_vec().try_into().unwrap()),
+		..Default::default()
+	}
+}
+
+#[test]
+fn editing_subaccounts_should_work() {
+	new_test_ext().execute_with(|| {
+		let data = |x| Data::Raw(vec![x; 1].try_into().unwrap());
+
+		assert_noop!(
+			Identity::add_sub(RuntimeOrigin::signed(10), 20, data(1)),
+			Error::<Test>::NoIdentity
+		);
+
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+
+		// first sub account
+		assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 1, data(1)));
+		assert_eq!(SuperOf::<Test>::get(1), Some((10, data(1))));
+		assert_eq!(Balances::free_balance(10), 80);
+
+		// second sub account
+		assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 2, data(2)));
+		assert_eq!(SuperOf::<Test>::get(1), Some((10, data(1))));
+		assert_eq!(SuperOf::<Test>::get(2), Some((10, data(2))));
+		assert_eq!(Balances::free_balance(10), 70);
+
+		// third sub account is too many
+		assert_noop!(
+			Identity::add_sub(RuntimeOrigin::signed(10), 3, data(3)),
+			Error::<Test>::TooManySubAccounts
+		);
+
+		// rename first sub account
+		assert_ok!(Identity::rename_sub(RuntimeOrigin::signed(10), 1, data(11)));
+		assert_eq!(SuperOf::<Test>::get(1), Some((10, data(11))));
+		assert_eq!(SuperOf::<Test>::get(2), Some((10, data(2))));
+		assert_eq!(Balances::free_balance(10), 70);
+
+		// remove first sub account
+		assert_ok!(Identity::remove_sub(RuntimeOrigin::signed(10), 1));
+		assert_eq!(SuperOf::<Test>::get(1), None);
+		assert_eq!(SuperOf::<Test>::get(2), Some((10, data(2))));
+		assert_eq!(Balances::free_balance(10), 80);
+
+		// add third sub account
+		assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 3, data(3)));
+		assert_eq!(SuperOf::<Test>::get(1), None);
+		assert_eq!(SuperOf::<Test>::get(2), Some((10, data(2))));
+		assert_eq!(SuperOf::<Test>::get(3), Some((10, data(3))));
+		assert_eq!(Balances::free_balance(10), 70);
+	});
+}
+
+#[test]
+fn resolving_subaccount_ownership_works() {
+	new_test_ext().execute_with(|| {
+		let data = |x| Data::Raw(vec![x; 1].try_into().unwrap());
+
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(20), Box::new(twenty())));
+
+		// 10 claims 1 as a subaccount
+		assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 1, data(1)));
+		assert_eq!(Balances::free_balance(1), 10);
+		assert_eq!(Balances::free_balance(10), 80);
+		assert_eq!(Balances::reserved_balance(10), 20);
+		// 20 cannot claim 1 now
+		assert_noop!(
+			Identity::add_sub(RuntimeOrigin::signed(20), 1, data(1)),
+			Error::<Test>::AlreadyClaimed
+		);
+		// 1 wants to be with 20 so it quits from 10
+		assert_ok!(Identity::quit_sub(RuntimeOrigin::signed(1)));
+		// 1 gets the 10 that 10 paid.
+		assert_eq!(Balances::free_balance(1), 20);
+		assert_eq!(Balances::free_balance(10), 80);
+		assert_eq!(Balances::reserved_balance(10), 10);
+		// 20 can claim 1 now
+		assert_ok!(Identity::add_sub(RuntimeOrigin::signed(20), 1, data(1)));
+	});
+}
+
+#[test]
+fn trailing_zeros_decodes_into_default_data() {
+	let encoded = Data::Raw(b"Hello".to_vec().try_into().unwrap()).encode();
+	assert!(<(Data, Data)>::decode(&mut &encoded[..]).is_err());
+	let input = &mut &encoded[..];
+	let (a, b) = <(Data, Data)>::decode(&mut AppendZerosInput::new(input)).unwrap();
+	assert_eq!(a, Data::Raw(b"Hello".to_vec().try_into().unwrap()));
+	assert_eq!(b, Data::None);
+}
+
+#[test]
+fn adding_registrar_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		let fields = IdentityFields(IdentityField::Display | IdentityField::Legal);
+		assert_ok!(Identity::set_fields(RuntimeOrigin::signed(3), 0, fields));
+		assert_eq!(
+			Identity::registrars(),
+			vec![Some(RegistrarInfo { account: 3, fee: 10, fields })]
+		);
+	});
+}
+
+#[test]
+fn amount_of_registrars_is_limited() {
+	new_test_ext().execute_with(|| {
+		for i in 1..MaxRegistrars::get() + 1 {
+			assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), i as u64));
+		}
+		let last_registrar = MaxRegistrars::get() as u64 + 1;
+		assert_noop!(
+			Identity::add_registrar(RuntimeOrigin::signed(1), last_registrar),
+			Error::<Test>::TooManyRegistrars
+		);
+	});
+}
+
+#[test]
+fn registration_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		let mut three_fields = ten();
+		three_fields.additional.try_push(Default::default()).unwrap();
+		three_fields.additional.try_push(Default::default()).unwrap();
+		assert!(three_fields.additional.try_push(Default::default()).is_err());
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_eq!(Identity::identity(10).unwrap().info, ten());
+		assert_eq!(Balances::free_balance(10), 90);
+		assert_ok!(Identity::clear_identity(RuntimeOrigin::signed(10)));
+		assert_eq!(Balances::free_balance(10), 100);
+		assert_noop!(Identity::clear_identity(RuntimeOrigin::signed(10)), Error::<Test>::NotNamed);
+	});
+}
+
+#[test]
+fn uninvited_judgement_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(3),
+				0,
+				10,
+				Judgement::Reasonable,
+				H256::random()
+			),
+			Error::<Test>::InvalidIndex
+		);
+
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(3),
+				0,
+				10,
+				Judgement::Reasonable,
+				H256::random()
+			),
+			Error::<Test>::InvalidTarget
+		);
+
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(3),
+				0,
+				10,
+				Judgement::Reasonable,
+				H256::random()
+			),
+			Error::<Test>::JudgementForDifferentIdentity
+		);
+
+		let identity_hash = BlakeTwo256::hash_of(&ten());
+
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(10),
+				0,
+				10,
+				Judgement::Reasonable,
+				identity_hash
+			),
+			Error::<Test>::InvalidIndex
+		);
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(3),
+				0,
+				10,
+				Judgement::FeePaid(1),
+				identity_hash
+			),
+			Error::<Test>::InvalidJudgement
+		);
+
+		assert_ok!(Identity::provide_judgement(
+			RuntimeOrigin::signed(3),
+			0,
+			10,
+			Judgement::Reasonable,
+			identity_hash
+		));
+		assert_eq!(Identity::identity(10).unwrap().judgements, vec![(0, Judgement::Reasonable)]);
+	});
+}
+
+#[test]
+fn clearing_judgement_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::provide_judgement(
+			RuntimeOrigin::signed(3),
+			0,
+			10,
+			Judgement::Reasonable,
+			BlakeTwo256::hash_of(&ten())
+		));
+		assert_ok!(Identity::clear_identity(RuntimeOrigin::signed(10)));
+		assert_eq!(Identity::identity(10), None);
+	});
+}
+
+#[test]
+fn killing_slashing_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_noop!(Identity::kill_identity(RuntimeOrigin::signed(1), 10), BadOrigin);
+		assert_ok!(Identity::kill_identity(RuntimeOrigin::signed(2), 10));
+		assert_eq!(Identity::identity(10), None);
+		assert_eq!(Balances::free_balance(10), 90);
+		assert_noop!(
+			Identity::kill_identity(RuntimeOrigin::signed(2), 10),
+			Error::<Test>::NotNamed
+		);
+	});
+}
+
+#[test]
+fn setting_subaccounts_should_work() {
+	new_test_ext().execute_with(|| {
+		let mut subs = vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))];
+		assert_noop!(
+			Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()),
+			Error::<Test>::NotFound
+		);
+
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()));
+		assert_eq!(Balances::free_balance(10), 80);
+		assert_eq!(Identity::subs_of(10), (10, vec![20].try_into().unwrap()));
+		assert_eq!(Identity::super_of(20), Some((10, Data::Raw(vec![40; 1].try_into().unwrap()))));
+
+		// push another item and re-set it.
+		subs.push((30, Data::Raw(vec![50; 1].try_into().unwrap())));
+		assert_ok!(Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()));
+		assert_eq!(Balances::free_balance(10), 70);
+		assert_eq!(Identity::subs_of(10), (20, vec![20, 30].try_into().unwrap()));
+		assert_eq!(Identity::super_of(20), Some((10, Data::Raw(vec![40; 1].try_into().unwrap()))));
+		assert_eq!(Identity::super_of(30), Some((10, Data::Raw(vec![50; 1].try_into().unwrap()))));
+
+		// switch out one of the items and re-set.
+		subs[0] = (40, Data::Raw(vec![60; 1].try_into().unwrap()));
+		assert_ok!(Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()));
+		assert_eq!(Balances::free_balance(10), 70); // no change in the balance
+		assert_eq!(Identity::subs_of(10), (20, vec![40, 30].try_into().unwrap()));
+		assert_eq!(Identity::super_of(20), None);
+		assert_eq!(Identity::super_of(30), Some((10, Data::Raw(vec![50; 1].try_into().unwrap()))));
+		assert_eq!(Identity::super_of(40), Some((10, Data::Raw(vec![60; 1].try_into().unwrap()))));
+
+		// clear
+		assert_ok!(Identity::set_subs(RuntimeOrigin::signed(10), vec![]));
+		assert_eq!(Balances::free_balance(10), 90);
+		assert_eq!(Identity::subs_of(10), (0, BoundedVec::default()));
+		assert_eq!(Identity::super_of(30), None);
+		assert_eq!(Identity::super_of(40), None);
+
+		subs.push((20, Data::Raw(vec![40; 1].try_into().unwrap())));
+		assert_noop!(
+			Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()),
+			Error::<Test>::TooManySubAccounts
+		);
+	});
+}
+
+#[test]
+fn clearing_account_should_remove_subaccounts_and_refund() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::set_subs(
+			RuntimeOrigin::signed(10),
+			vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))]
+		));
+		assert_ok!(Identity::clear_identity(RuntimeOrigin::signed(10)));
+		assert_eq!(Balances::free_balance(10), 100);
+		assert!(Identity::super_of(20).is_none());
+	});
+}
+
+#[test]
+fn killing_account_should_remove_subaccounts_and_not_refund() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::set_subs(
+			RuntimeOrigin::signed(10),
+			vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))]
+		));
+		assert_ok!(Identity::kill_identity(RuntimeOrigin::signed(2), 10));
+		assert_eq!(Balances::free_balance(10), 80);
+		assert!(Identity::super_of(20).is_none());
+	});
+}
+
+#[test]
+fn cancelling_requested_judgement_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		assert_noop!(
+			Identity::cancel_request(RuntimeOrigin::signed(10), 0),
+			Error::<Test>::NoIdentity
+		);
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10));
+		assert_ok!(Identity::cancel_request(RuntimeOrigin::signed(10), 0));
+		assert_eq!(Balances::free_balance(10), 90);
+		assert_noop!(
+			Identity::cancel_request(RuntimeOrigin::signed(10), 0),
+			Error::<Test>::NotFound
+		);
+
+		assert_ok!(Identity::provide_judgement(
+			RuntimeOrigin::signed(3),
+			0,
+			10,
+			Judgement::Reasonable,
+			BlakeTwo256::hash_of(&ten())
+		));
+		assert_noop!(
+			Identity::cancel_request(RuntimeOrigin::signed(10), 0),
+			Error::<Test>::JudgementGiven
+		);
+	});
+}
+
+#[test]
+fn requesting_judgement_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_noop!(
+			Identity::request_judgement(RuntimeOrigin::signed(10), 0, 9),
+			Error::<Test>::FeeChanged
+		);
+		assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10));
+		// 10 for the judgement request, 10 for the identity.
+		assert_eq!(Balances::free_balance(10), 80);
+
+		// Re-requesting won't work as we already paid.
+		assert_noop!(
+			Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10),
+			Error::<Test>::StickyJudgement
+		);
+		assert_ok!(Identity::provide_judgement(
+			RuntimeOrigin::signed(3),
+			0,
+			10,
+			Judgement::Erroneous,
+			BlakeTwo256::hash_of(&ten())
+		));
+		// Registrar got their payment now.
+		assert_eq!(Balances::free_balance(3), 20);
+
+		// Re-requesting still won't work as it's erroneous.
+		assert_noop!(
+			Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10),
+			Error::<Test>::StickyJudgement
+		);
+
+		// Requesting from a second registrar still works.
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 4));
+		assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 1, 10));
+
+		// Re-requesting after the judgement has been reduced works.
+		assert_ok!(Identity::provide_judgement(
+			RuntimeOrigin::signed(3),
+			0,
+			10,
+			Judgement::OutOfDate,
+			BlakeTwo256::hash_of(&ten())
+		));
+		assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10));
+	});
+}
+
+#[test]
+fn provide_judgement_should_return_judgement_payment_failed_error() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10));
+		// 10 for the judgement request, 10 for the identity.
+		assert_eq!(Balances::free_balance(10), 80);
+
+		// This forces judgement payment failed error
+		Balances::make_free_balance_be(&3, 0);
+		assert_noop!(
+			Identity::provide_judgement(
+				RuntimeOrigin::signed(3),
+				0,
+				10,
+				Judgement::Erroneous,
+				BlakeTwo256::hash_of(&ten())
+			),
+			Error::<Test>::JudgementPaymentFailed
+		);
+	});
+}
+
+#[test]
+fn field_deposit_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		assert_ok!(Identity::set_fee(RuntimeOrigin::signed(3), 0, 10));
+		assert_ok!(Identity::set_identity(
+			RuntimeOrigin::signed(10),
+			Box::new(IdentityInfo {
+				additional: vec![
+					(
+						Data::Raw(b"number".to_vec().try_into().unwrap()),
+						Data::Raw(10u32.encode().try_into().unwrap())
+					),
+					(
+						Data::Raw(b"text".to_vec().try_into().unwrap()),
+						Data::Raw(b"10".to_vec().try_into().unwrap())
+					),
+				]
+				.try_into()
+				.unwrap(),
+				..Default::default()
+			})
+		));
+		assert_eq!(Balances::free_balance(10), 70);
+	});
+}
+
+#[test]
+fn setting_account_id_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::add_registrar(RuntimeOrigin::signed(1), 3));
+		// account 4 cannot change the first registrar's identity since it's owned by 3.
+		assert_noop!(
+			Identity::set_account_id(RuntimeOrigin::signed(4), 0, 3),
+			Error::<Test>::InvalidIndex
+		);
+		// account 3 can, because that's the registrar's current account.
+		assert_ok!(Identity::set_account_id(RuntimeOrigin::signed(3), 0, 4));
+		// account 4 can now, because that's their new ID.
+		assert_ok!(Identity::set_account_id(RuntimeOrigin::signed(4), 0, 3));
+	});
+}
+
+#[test]
+fn test_has_identity() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
+		assert!(Identity::has_identity(&10, IdentityField::Display as u64));
+		assert!(Identity::has_identity(&10, IdentityField::Legal as u64));
+		assert!(Identity::has_identity(
+			&10,
+			IdentityField::Display as u64 | IdentityField::Legal as u64
+		));
+		assert!(!Identity::has_identity(
+			&10,
+			IdentityField::Display as u64 | IdentityField::Legal as u64 | IdentityField::Web as u64
+		));
+	});
+}
addedpallets/identity/src/types.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/src/types.rs
@@ -0,0 +1,518 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use super::*;
+use codec::{Decode, Encode, MaxEncodedLen};
+use enumflags2::{bitflags, BitFlags};
+use frame_support::{
+	traits::{ConstU32, Get},
+	BoundedVec, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound,
+};
+use scale_info::{
+	build::{Fields, Variants},
+	meta_type, Path, Type, TypeInfo, TypeParameter,
+};
+use sp_runtime::{traits::Zero, RuntimeDebug};
+use sp_std::{fmt::Debug, iter::once, ops::Add, prelude::*};
+
+/// Either underlying data blob if it is at most 32 bytes, or a hash of it. If the data is greater
+/// than 32-bytes then it will be truncated when encoding.
+///
+/// Can also be `None`.
+#[derive(Clone, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+pub enum Data {
+	/// No data here.
+	None,
+	/// The data is stored directly.
+	Raw(BoundedVec<u8, ConstU32<32>>),
+	/// Only the Blake2 hash of the data is stored. The preimage of the hash may be retrieved
+	/// through some hash-lookup service.
+	BlakeTwo256([u8; 32]),
+	/// Only the SHA2-256 hash of the data is stored. The preimage of the hash may be retrieved
+	/// through some hash-lookup service.
+	Sha256([u8; 32]),
+	/// Only the Keccak-256 hash of the data is stored. The preimage of the hash may be retrieved
+	/// through some hash-lookup service.
+	Keccak256([u8; 32]),
+	/// Only the SHA3-256 hash of the data is stored. The preimage of the hash may be retrieved
+	/// through some hash-lookup service.
+	ShaThree256([u8; 32]),
+}
+
+impl Data {
+	pub fn is_none(&self) -> bool {
+		self == &Data::None
+	}
+}
+
+impl Decode for Data {
+	fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
+		let b = input.read_byte()?;
+		Ok(match b {
+			0 => Data::None,
+			n @ 1..=33 => {
+				let mut r: BoundedVec<_, _> = vec![0u8; n as usize - 1]
+					.try_into()
+					.expect("bound checked in match arm condition; qed");
+				input.read(&mut r[..])?;
+				Data::Raw(r)
+			},
+			34 => Data::BlakeTwo256(<[u8; 32]>::decode(input)?),
+			35 => Data::Sha256(<[u8; 32]>::decode(input)?),
+			36 => Data::Keccak256(<[u8; 32]>::decode(input)?),
+			37 => Data::ShaThree256(<[u8; 32]>::decode(input)?),
+			_ => return Err(codec::Error::from("invalid leading byte")),
+		})
+	}
+}
+
+impl Encode for Data {
+	fn encode(&self) -> Vec<u8> {
+		match self {
+			Data::None => vec![0u8; 1],
+			Data::Raw(ref x) => {
+				let l = x.len().min(32);
+				let mut r = vec![l as u8 + 1; l + 1];
+				r[1..].copy_from_slice(&x[..l as usize]);
+				r
+			},
+			Data::BlakeTwo256(ref h) => once(34u8).chain(h.iter().cloned()).collect(),
+			Data::Sha256(ref h) => once(35u8).chain(h.iter().cloned()).collect(),
+			Data::Keccak256(ref h) => once(36u8).chain(h.iter().cloned()).collect(),
+			Data::ShaThree256(ref h) => once(37u8).chain(h.iter().cloned()).collect(),
+		}
+	}
+}
+impl codec::EncodeLike for Data {}
+
+/// Add a Raw variant with the given index and a fixed sized byte array
+macro_rules! data_raw_variants {
+    ($variants:ident, $(($index:literal, $size:literal)),* ) => {
+		$variants
+		$(
+			.variant(concat!("Raw", stringify!($size)), |v| v
+				.index($index)
+				.fields(Fields::unnamed().field(|f| f.ty::<[u8; $size]>()))
+			)
+		)*
+    }
+}
+
+impl TypeInfo for Data {
+	type Identity = Self;
+
+	fn type_info() -> Type {
+		let variants = Variants::new().variant("None", |v| v.index(0));
+
+		// create a variant for all sizes of Raw data from 0-32
+		let variants = data_raw_variants!(
+			variants,
+			(1, 0),
+			(2, 1),
+			(3, 2),
+			(4, 3),
+			(5, 4),
+			(6, 5),
+			(7, 6),
+			(8, 7),
+			(9, 8),
+			(10, 9),
+			(11, 10),
+			(12, 11),
+			(13, 12),
+			(14, 13),
+			(15, 14),
+			(16, 15),
+			(17, 16),
+			(18, 17),
+			(19, 18),
+			(20, 19),
+			(21, 20),
+			(22, 21),
+			(23, 22),
+			(24, 23),
+			(25, 24),
+			(26, 25),
+			(27, 26),
+			(28, 27),
+			(29, 28),
+			(30, 29),
+			(31, 30),
+			(32, 31),
+			(33, 32)
+		);
+
+		let variants = variants
+			.variant("BlakeTwo256", |v| {
+				v.index(34).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("Sha256", |v| {
+				v.index(35).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("Keccak256", |v| {
+				v.index(36).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("ShaThree256", |v| {
+				v.index(37).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			});
+
+		Type::builder().path(Path::new("Data", module_path!())).variant(variants)
+	}
+}
+
+impl Default for Data {
+	fn default() -> Self {
+		Self::None
+	}
+}
+
+/// An identifier for a single name registrar/identity verification service.
+pub type RegistrarIndex = u32;
+
+/// An attestation of a registrar over how accurate some `IdentityInfo` is in describing an account.
+///
+/// NOTE: Registrars may pay little attention to some fields. Registrars may want to make clear
+/// which fields their attestation is relevant for by off-chain means.
+#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+pub enum Judgement<Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq>
+{
+	/// The default value; no opinion is held.
+	Unknown,
+	/// No judgement is yet in place, but a deposit is reserved as payment for providing one.
+	FeePaid(Balance),
+	/// The data appears to be reasonably acceptable in terms of its accuracy, however no in depth
+	/// checks (such as in-person meetings or formal KYC) have been conducted.
+	Reasonable,
+	/// The target is known directly by the registrar and the registrar can fully attest to the
+	/// the data's accuracy.
+	KnownGood,
+	/// The data was once good but is currently out of date. There is no malicious intent in the
+	/// inaccuracy. This judgement can be removed through updating the data.
+	OutOfDate,
+	/// The data is imprecise or of sufficiently low-quality to be problematic. It is not
+	/// indicative of malicious intent. This judgement can be removed through updating the data.
+	LowQuality,
+	/// The data is erroneous. This may be indicative of malicious intent. This cannot be removed
+	/// except by the registrar.
+	Erroneous,
+}
+
+impl<Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq>
+	Judgement<Balance>
+{
+	/// Returns `true` if this judgement is indicative of a deposit being currently held. This means
+	/// it should not be cleared or replaced except by an operation which utilizes the deposit.
+	pub(crate) fn has_deposit(&self) -> bool {
+		matches!(self, Judgement::FeePaid(_))
+	}
+
+	/// Returns `true` if this judgement is one that should not be generally be replaced outside
+	/// of specialized handlers. Examples include "malicious" judgements and deposit-holding
+	/// judgements.
+	pub(crate) fn is_sticky(&self) -> bool {
+		matches!(self, Judgement::FeePaid(_) | Judgement::Erroneous)
+	}
+}
+
+/// The fields that we use to identify the owner of an account with. Each corresponds to a field
+/// in the `IdentityInfo` struct.
+#[bitflags]
+#[repr(u64)]
+#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+pub enum IdentityField {
+	Display = 0b0000000000000000000000000000000000000000000000000000000000000001,
+	Legal = 0b0000000000000000000000000000000000000000000000000000000000000010,
+	Web = 0b0000000000000000000000000000000000000000000000000000000000000100,
+	Riot = 0b0000000000000000000000000000000000000000000000000000000000001000,
+	Email = 0b0000000000000000000000000000000000000000000000000000000000010000,
+	PgpFingerprint = 0b0000000000000000000000000000000000000000000000000000000000100000,
+	Image = 0b0000000000000000000000000000000000000000000000000000000001000000,
+	Twitter = 0b0000000000000000000000000000000000000000000000000000000010000000,
+}
+
+/// Wrapper type for `BitFlags<IdentityField>` that implements `Codec`.
+#[derive(Clone, Copy, PartialEq, Default, RuntimeDebug)]
+pub struct IdentityFields(pub BitFlags<IdentityField>);
+
+impl MaxEncodedLen for IdentityFields {
+	fn max_encoded_len() -> usize {
+		u64::max_encoded_len()
+	}
+}
+
+impl Eq for IdentityFields {}
+impl Encode for IdentityFields {
+	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		self.0.bits().using_encoded(f)
+	}
+}
+impl Decode for IdentityFields {
+	fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
+		let field = u64::decode(input)?;
+		Ok(Self(<BitFlags<IdentityField>>::from_bits(field as u64).map_err(|_| "invalid value")?))
+	}
+}
+impl TypeInfo for IdentityFields {
+	type Identity = Self;
+
+	fn type_info() -> Type {
+		Type::builder()
+			.path(Path::new("BitFlags", module_path!()))
+			.type_params(vec![TypeParameter::new("T", Some(meta_type::<IdentityField>()))])
+			.composite(Fields::unnamed().field(|f| f.ty::<u64>().type_name("IdentityField")))
+	}
+}
+
+/// Information concerning the identity of the controller of an account.
+///
+/// NOTE: This should be stored at the end of the storage item to facilitate the addition of extra
+/// fields in a backwards compatible way through a specialized `Decode` impl.
+#[derive(
+	CloneNoBound, Encode, Decode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+)]
+#[codec(mel_bound())]
+#[cfg_attr(test, derive(frame_support::DefaultNoBound))]
+#[scale_info(skip_type_params(FieldLimit))]
+pub struct IdentityInfo<FieldLimit: Get<u32>> {
+	/// Additional fields of the identity that are not catered for with the struct's explicit
+	/// fields.
+	pub additional: BoundedVec<(Data, Data), FieldLimit>,
+
+	/// A reasonable display name for the controller of the account. This should be whatever it is
+	/// that it is typically known as and should not be confusable with other entities, given
+	/// reasonable context.
+	///
+	/// Stored as UTF-8.
+	pub display: Data,
+
+	/// The full legal name in the local jurisdiction of the entity. This might be a bit
+	/// long-winded.
+	///
+	/// Stored as UTF-8.
+	pub legal: Data,
+
+	/// A representative website held by the controller of the account.
+	///
+	/// NOTE: `https://` is automatically prepended.
+	///
+	/// Stored as UTF-8.
+	pub web: Data,
+
+	/// The Riot/Matrix handle held by the controller of the account.
+	///
+	/// Stored as UTF-8.
+	pub riot: Data,
+
+	/// The email address of the controller of the account.
+	///
+	/// Stored as UTF-8.
+	pub email: Data,
+
+	/// The PGP/GPG public key of the controller of the account.
+	pub pgp_fingerprint: Option<[u8; 20]>,
+
+	/// A graphic image representing the controller of the account. Should be a company,
+	/// organization or project logo or a headshot in the case of a human.
+	pub image: Data,
+
+	/// The Twitter identity. The leading `@` character may be elided.
+	pub twitter: Data,
+}
+
+impl<FieldLimit: Get<u32>> IdentityInfo<FieldLimit> {
+	pub(crate) fn fields(&self) -> IdentityFields {
+		let mut res = <BitFlags<IdentityField>>::empty();
+		if !self.display.is_none() {
+			res.insert(IdentityField::Display);
+		}
+		if !self.legal.is_none() {
+			res.insert(IdentityField::Legal);
+		}
+		if !self.web.is_none() {
+			res.insert(IdentityField::Web);
+		}
+		if !self.riot.is_none() {
+			res.insert(IdentityField::Riot);
+		}
+		if !self.email.is_none() {
+			res.insert(IdentityField::Email);
+		}
+		if self.pgp_fingerprint.is_some() {
+			res.insert(IdentityField::PgpFingerprint);
+		}
+		if !self.image.is_none() {
+			res.insert(IdentityField::Image);
+		}
+		if !self.twitter.is_none() {
+			res.insert(IdentityField::Twitter);
+		}
+		IdentityFields(res)
+	}
+}
+
+/// Information concerning the identity of the controller of an account.
+///
+/// NOTE: This is stored separately primarily to facilitate the addition of extra fields in a
+/// backwards compatible way through a specialized `Decode` impl.
+#[derive(
+	CloneNoBound, Encode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+)]
+#[codec(mel_bound())]
+#[scale_info(skip_type_params(MaxJudgements, MaxAdditionalFields))]
+pub struct Registration<
+	Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq,
+	MaxJudgements: Get<u32>,
+	MaxAdditionalFields: Get<u32>,
+> {
+	/// Judgements from the registrars on this identity. Stored ordered by `RegistrarIndex`. There
+	/// may be only a single judgement from each registrar.
+	pub judgements: BoundedVec<(RegistrarIndex, Judgement<Balance>), MaxJudgements>,
+
+	/// Amount held on deposit for this information.
+	pub deposit: Balance,
+
+	/// Information on the identity.
+	pub info: IdentityInfo<MaxAdditionalFields>,
+}
+
+impl<
+		Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq + Zero + Add,
+		MaxJudgements: Get<u32>,
+		MaxAdditionalFields: Get<u32>,
+	> Registration<Balance, MaxJudgements, MaxAdditionalFields>
+{
+	pub(crate) fn total_deposit(&self) -> Balance {
+		self.deposit +
+			self.judgements
+				.iter()
+				.map(|(_, ref j)| if let Judgement::FeePaid(fee) = j { *fee } else { Zero::zero() })
+				.fold(Zero::zero(), |a, i| a + i)
+	}
+}
+
+impl<
+		Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq,
+		MaxJudgements: Get<u32>,
+		MaxAdditionalFields: Get<u32>,
+	> Decode for Registration<Balance, MaxJudgements, MaxAdditionalFields>
+{
+	fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
+		let (judgements, deposit, info) = Decode::decode(&mut AppendZerosInput::new(input))?;
+		Ok(Self { judgements, deposit, info })
+	}
+}
+
+/// Information concerning a registrar.
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
+pub struct RegistrarInfo<
+	Balance: Encode + Decode + Clone + Debug + Eq + PartialEq,
+	AccountId: Encode + Decode + Clone + Debug + Eq + PartialEq,
+> {
+	/// The account of the registrar.
+	pub account: AccountId,
+
+	/// Amount required to be given to the registrar for them to provide judgement.
+	pub fee: Balance,
+
+	/// Relevant fields for this registrar. Registrar judgements are limited to attestations on
+	/// these fields.
+	pub fields: IdentityFields,
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+
+	#[test]
+	fn manual_data_type_info() {
+		let mut registry = scale_info::Registry::new();
+		let type_id = registry.register_type(&scale_info::meta_type::<Data>());
+		let registry: scale_info::PortableRegistry = registry.into();
+		let type_info = registry.resolve(type_id.id()).unwrap();
+
+		let check_type_info = |data: &Data| {
+			let variant_name = match data {
+				Data::None => "None".to_string(),
+				Data::BlakeTwo256(_) => "BlakeTwo256".to_string(),
+				Data::Sha256(_) => "Sha256".to_string(),
+				Data::Keccak256(_) => "Keccak256".to_string(),
+				Data::ShaThree256(_) => "ShaThree256".to_string(),
+				Data::Raw(bytes) => format!("Raw{}", bytes.len()),
+			};
+			if let scale_info::TypeDef::Variant(variant) = type_info.type_def() {
+				let variant = variant
+					.variants()
+					.iter()
+					.find(|v| v.name() == &variant_name)
+					.expect(&format!("Expected to find variant {}", variant_name));
+
+				let field_arr_len = variant
+					.fields()
+					.first()
+					.and_then(|f| registry.resolve(f.ty().id()))
+					.map(|ty| {
+						if let scale_info::TypeDef::Array(arr) = ty.type_def() {
+							arr.len()
+						} else {
+							panic!("Should be an array type")
+						}
+					})
+					.unwrap_or(0);
+
+				let encoded = data.encode();
+				assert_eq!(encoded[0], variant.index());
+				assert_eq!(encoded.len() as u32 - 1, field_arr_len);
+			} else {
+				panic!("Should be a variant type")
+			};
+		};
+
+		let mut data = vec![
+			Data::None,
+			Data::BlakeTwo256(Default::default()),
+			Data::Sha256(Default::default()),
+			Data::Keccak256(Default::default()),
+			Data::ShaThree256(Default::default()),
+		];
+
+		// A Raw instance for all possible sizes of the Raw data
+		for n in 0..32 {
+			data.push(Data::Raw(vec![0u8; n as usize].try_into().unwrap()))
+		}
+
+		for d in data.iter() {
+			check_type_info(d);
+		}
+	}
+}
addedpallets/identity/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/identity/src/weights.rs
@@ -0,0 +1,504 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// Copyright (C) 2022 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for pallet_identity
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-11-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
+
+// Executed Command:
+// ./target/production/substrate
+// benchmark
+// pallet
+// --chain=dev
+// --steps=50
+// --repeat=20
+// --pallet=pallet_identity
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=./frame/identity/src/weights.rs
+// --header=./HEADER-APACHE2
+// --template=./.maintain/frame-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_identity.
+pub trait WeightInfo {
+	fn add_registrar(r: u32, ) -> Weight;
+	fn set_identity(r: u32, x: u32, ) -> Weight;
+	fn set_subs_new(s: u32, ) -> Weight;
+	fn set_subs_old(p: u32, ) -> Weight;
+	fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight;
+	fn request_judgement(r: u32, x: u32, ) -> Weight;
+	fn cancel_request(r: u32, x: u32, ) -> Weight;
+	fn set_fee(r: u32, ) -> Weight;
+	fn set_account_id(r: u32, ) -> Weight;
+	fn set_fields(r: u32, ) -> Weight;
+	fn provide_judgement(r: u32, x: u32, ) -> Weight;
+	fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight;
+	fn add_sub(s: u32, ) -> Weight;
+	fn rename_sub(s: u32, ) -> Weight;
+	fn remove_sub(s: u32, ) -> Weight;
+	fn quit_sub(s: u32, ) -> Weight;
+}
+
+/// Weights for pallet_identity using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn add_registrar(r: u32, ) -> Weight {
+		// Minimum execution time: 20_269 nanoseconds.
+		Weight::from_ref_time(21_910_543 as u64)
+			// Standard Error: 4_604
+			.saturating_add(Weight::from_ref_time(223_104 as u64).saturating_mul(r as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn set_identity(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 41_872 nanoseconds.
+		Weight::from_ref_time(40_230_216 as u64)
+			// Standard Error: 2_342
+			.saturating_add(Weight::from_ref_time(145_168 as u64).saturating_mul(r as u64))
+			// Standard Error: 457
+			.saturating_add(Weight::from_ref_time(291_732 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:2 w:2)
+	/// The range of component `s` is `[0, 100]`.
+	fn set_subs_new(s: u32, ) -> Weight {
+		// Minimum execution time: 12_024 nanoseconds.
+		Weight::from_ref_time(32_550_819 as u64)
+			// Standard Error: 5_057
+			.saturating_add(Weight::from_ref_time(2_521_245 as u64).saturating_mul(s as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+			.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:2)
+	/// The range of component `p` is `[0, 100]`.
+	fn set_subs_old(p: u32, ) -> Weight {
+		// Minimum execution time: 12_232 nanoseconds.
+		Weight::from_ref_time(34_009_761 as u64)
+			// Standard Error: 5_047
+			.saturating_add(Weight::from_ref_time(1_113_100 as u64).saturating_mul(p as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+			.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64)))
+	}
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:100)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `s` is `[0, 100]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 57_144 nanoseconds.
+		Weight::from_ref_time(41_559_247 as u64)
+			// Standard Error: 9_996
+			.saturating_add(Weight::from_ref_time(146_770 as u64).saturating_mul(r as u64))
+			// Standard Error: 1_952
+			.saturating_add(Weight::from_ref_time(1_086_673 as u64).saturating_mul(s as u64))
+			// Standard Error: 1_952
+			.saturating_add(Weight::from_ref_time(162_481 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+			.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity Registrars (r:1 w:0)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn request_judgement(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 44_726 nanoseconds.
+		Weight::from_ref_time(41_637_308 as u64)
+			// Standard Error: 1_907
+			.saturating_add(Weight::from_ref_time(219_078 as u64).saturating_mul(r as u64))
+			// Standard Error: 372
+			.saturating_add(Weight::from_ref_time(309_888 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn cancel_request(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 39_719 nanoseconds.
+		Weight::from_ref_time(38_008_751 as u64)
+			// Standard Error: 2_394
+			.saturating_add(Weight::from_ref_time(181_870 as u64).saturating_mul(r as u64))
+			// Standard Error: 467
+			.saturating_add(Weight::from_ref_time(314_990 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_fee(r: u32, ) -> Weight {
+		// Minimum execution time: 10_634 nanoseconds.
+		Weight::from_ref_time(11_383_704 as u64)
+			// Standard Error: 2_250
+			.saturating_add(Weight::from_ref_time(193_094 as u64).saturating_mul(r as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_account_id(r: u32, ) -> Weight {
+		// Minimum execution time: 10_840 nanoseconds.
+		Weight::from_ref_time(11_638_740 as u64)
+			// Standard Error: 1_985
+			.saturating_add(Weight::from_ref_time(193_016 as u64).saturating_mul(r as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_fields(r: u32, ) -> Weight {
+		// Minimum execution time: 10_748 nanoseconds.
+		Weight::from_ref_time(11_346_901 as u64)
+			// Standard Error: 2_132
+			.saturating_add(Weight::from_ref_time(196_630 as u64).saturating_mul(r as u64))
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:0)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn provide_judgement(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 33_682 nanoseconds.
+		Weight::from_ref_time(31_336_603 as u64)
+			// Standard Error: 3_056
+			.saturating_add(Weight::from_ref_time(200_403 as u64).saturating_mul(r as u64))
+			// Standard Error: 565
+			.saturating_add(Weight::from_ref_time(525_142 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:100)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `s` is `[0, 100]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 68_794 nanoseconds.
+		Weight::from_ref_time(52_114_486 as u64)
+			// Standard Error: 4_808
+			.saturating_add(Weight::from_ref_time(153_462 as u64).saturating_mul(r as u64))
+			// Standard Error: 939
+			.saturating_add(Weight::from_ref_time(1_084_612 as u64).saturating_mul(s as u64))
+			// Standard Error: 939
+			.saturating_add(Weight::from_ref_time(170_112 as u64).saturating_mul(x as u64))
+			.saturating_add(T::DbWeight::get().reads(3 as u64))
+			.saturating_add(T::DbWeight::get().writes(3 as u64))
+			.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[0, 99]`.
+	fn add_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 37_914 nanoseconds.
+		Weight::from_ref_time(43_488_083 as u64)
+			// Standard Error: 1_631
+			.saturating_add(Weight::from_ref_time(118_845 as u64).saturating_mul(s as u64))
+			.saturating_add(T::DbWeight::get().reads(3 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	/// The range of component `s` is `[1, 100]`.
+	fn rename_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 16_124 nanoseconds.
+		Weight::from_ref_time(18_580_462 as u64)
+			// Standard Error: 688
+			.saturating_add(Weight::from_ref_time(67_220 as u64).saturating_mul(s as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[1, 100]`.
+	fn remove_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 41_517 nanoseconds.
+		Weight::from_ref_time(45_123_530 as u64)
+			// Standard Error: 1_530
+			.saturating_add(Weight::from_ref_time(105_429 as u64).saturating_mul(s as u64))
+			.saturating_add(T::DbWeight::get().reads(3 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[0, 99]`.
+	fn quit_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 30_171 nanoseconds.
+		Weight::from_ref_time(33_355_514 as u64)
+			// Standard Error: 1_286
+			.saturating_add(Weight::from_ref_time(114_716 as u64).saturating_mul(s as u64))
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn add_registrar(r: u32, ) -> Weight {
+		// Minimum execution time: 20_269 nanoseconds.
+		Weight::from_ref_time(21_910_543 as u64)
+			// Standard Error: 4_604
+			.saturating_add(Weight::from_ref_time(223_104 as u64).saturating_mul(r as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn set_identity(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 41_872 nanoseconds.
+		Weight::from_ref_time(40_230_216 as u64)
+			// Standard Error: 2_342
+			.saturating_add(Weight::from_ref_time(145_168 as u64).saturating_mul(r as u64))
+			// Standard Error: 457
+			.saturating_add(Weight::from_ref_time(291_732 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:2 w:2)
+	/// The range of component `s` is `[0, 100]`.
+	fn set_subs_new(s: u32, ) -> Weight {
+		// Minimum execution time: 12_024 nanoseconds.
+		Weight::from_ref_time(32_550_819 as u64)
+			// Standard Error: 5_057
+			.saturating_add(Weight::from_ref_time(2_521_245 as u64).saturating_mul(s as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:2)
+	/// The range of component `p` is `[0, 100]`.
+	fn set_subs_old(p: u32, ) -> Weight {
+		// Minimum execution time: 12_232 nanoseconds.
+		Weight::from_ref_time(34_009_761 as u64)
+			// Standard Error: 5_047
+			.saturating_add(Weight::from_ref_time(1_113_100 as u64).saturating_mul(p as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(p as u64)))
+	}
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:100)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `s` is `[0, 100]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 57_144 nanoseconds.
+		Weight::from_ref_time(41_559_247 as u64)
+			// Standard Error: 9_996
+			.saturating_add(Weight::from_ref_time(146_770 as u64).saturating_mul(r as u64))
+			// Standard Error: 1_952
+			.saturating_add(Weight::from_ref_time(1_086_673 as u64).saturating_mul(s as u64))
+			// Standard Error: 1_952
+			.saturating_add(Weight::from_ref_time(162_481 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity Registrars (r:1 w:0)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn request_judgement(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 44_726 nanoseconds.
+		Weight::from_ref_time(41_637_308 as u64)
+			// Standard Error: 1_907
+			.saturating_add(Weight::from_ref_time(219_078 as u64).saturating_mul(r as u64))
+			// Standard Error: 372
+			.saturating_add(Weight::from_ref_time(309_888 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn cancel_request(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 39_719 nanoseconds.
+		Weight::from_ref_time(38_008_751 as u64)
+			// Standard Error: 2_394
+			.saturating_add(Weight::from_ref_time(181_870 as u64).saturating_mul(r as u64))
+			// Standard Error: 467
+			.saturating_add(Weight::from_ref_time(314_990 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_fee(r: u32, ) -> Weight {
+		// Minimum execution time: 10_634 nanoseconds.
+		Weight::from_ref_time(11_383_704 as u64)
+			// Standard Error: 2_250
+			.saturating_add(Weight::from_ref_time(193_094 as u64).saturating_mul(r as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_account_id(r: u32, ) -> Weight {
+		// Minimum execution time: 10_840 nanoseconds.
+		Weight::from_ref_time(11_638_740 as u64)
+			// Standard Error: 1_985
+			.saturating_add(Weight::from_ref_time(193_016 as u64).saturating_mul(r as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	fn set_fields(r: u32, ) -> Weight {
+		// Minimum execution time: 10_748 nanoseconds.
+		Weight::from_ref_time(11_346_901 as u64)
+			// Standard Error: 2_132
+			.saturating_add(Weight::from_ref_time(196_630 as u64).saturating_mul(r as u64))
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity Registrars (r:1 w:0)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	/// The range of component `r` is `[1, 19]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn provide_judgement(r: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 33_682 nanoseconds.
+		Weight::from_ref_time(31_336_603 as u64)
+			// Standard Error: 3_056
+			.saturating_add(Weight::from_ref_time(200_403 as u64).saturating_mul(r as u64))
+			// Standard Error: 565
+			.saturating_add(Weight::from_ref_time(525_142 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity SubsOf (r:1 w:1)
+	// Storage: Identity IdentityOf (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: Identity SuperOf (r:0 w:100)
+	/// The range of component `r` is `[1, 20]`.
+	/// The range of component `s` is `[0, 100]`.
+	/// The range of component `x` is `[0, 100]`.
+	fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight {
+		// Minimum execution time: 68_794 nanoseconds.
+		Weight::from_ref_time(52_114_486 as u64)
+			// Standard Error: 4_808
+			.saturating_add(Weight::from_ref_time(153_462 as u64).saturating_mul(r as u64))
+			// Standard Error: 939
+			.saturating_add(Weight::from_ref_time(1_084_612 as u64).saturating_mul(s as u64))
+			// Standard Error: 939
+			.saturating_add(Weight::from_ref_time(170_112 as u64).saturating_mul(x as u64))
+			.saturating_add(RocksDbWeight::get().reads(3 as u64))
+			.saturating_add(RocksDbWeight::get().writes(3 as u64))
+			.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[0, 99]`.
+	fn add_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 37_914 nanoseconds.
+		Weight::from_ref_time(43_488_083 as u64)
+			// Standard Error: 1_631
+			.saturating_add(Weight::from_ref_time(118_845 as u64).saturating_mul(s as u64))
+			.saturating_add(RocksDbWeight::get().reads(3 as u64))
+			.saturating_add(RocksDbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	/// The range of component `s` is `[1, 100]`.
+	fn rename_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 16_124 nanoseconds.
+		Weight::from_ref_time(18_580_462 as u64)
+			// Standard Error: 688
+			.saturating_add(Weight::from_ref_time(67_220 as u64).saturating_mul(s as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Identity IdentityOf (r:1 w:0)
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[1, 100]`.
+	fn remove_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 41_517 nanoseconds.
+		Weight::from_ref_time(45_123_530 as u64)
+			// Standard Error: 1_530
+			.saturating_add(Weight::from_ref_time(105_429 as u64).saturating_mul(s as u64))
+			.saturating_add(RocksDbWeight::get().reads(3 as u64))
+			.saturating_add(RocksDbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity SuperOf (r:1 w:1)
+	// Storage: Identity SubsOf (r:1 w:1)
+	/// The range of component `s` is `[0, 99]`.
+	fn quit_sub(s: u32, ) -> Weight {
+		// Minimum execution time: 30_171 nanoseconds.
+		Weight::from_ref_time(33_355_514 as u64)
+			// Standard Error: 1_286
+			.saturating_add(Weight::from_ref_time(114_716 as u64).saturating_mul(s as u64))
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(2 as u64))
+	}
+}
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -276,11 +276,6 @@
 git = 'https://github.com/paritytech/substrate'
 branch = 'polkadot-v0.9.36'
 
-[dependencies.pallet-identity]
-default-features = false
-git = 'https://github.com/paritytech/substrate'
-branch = 'polkadot-v0.9.36'
-
 [dependencies.pallet-balances]
 default-features = false
 git = "https://github.com/paritytech/substrate"
@@ -505,6 +500,7 @@
 pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }
+pallet-identity = { default-features = false, path = "../../pallets/identity" }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
 pallet-structure = { default-features = false, path = "../../pallets/structure" }
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -260,11 +260,6 @@
 git = 'https://github.com/paritytech/substrate'
 branch = 'polkadot-v0.9.36'
 
-[dependencies.pallet-identity]
-default-features = false
-git = 'https://github.com/paritytech/substrate'
-branch = 'polkadot-v0.9.36'
-
 [dependencies.pallet-balances]
 default-features = false
 git = "https://github.com/paritytech/substrate"
@@ -496,6 +491,7 @@
 pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }
+pallet-identity = { default-features = false, path = "../../pallets/identity" }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
 pallet-structure = { default-features = false, path = "../../pallets/structure" }
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -260,11 +260,6 @@
 git = 'https://github.com/paritytech/substrate'
 branch = 'polkadot-v0.9.36'
 
-[dependencies.pallet-identity]
-default-features = false
-git = 'https://github.com/paritytech/substrate'
-branch = 'polkadot-v0.9.36'
-
 [dependencies.pallet-balances]
 default-features = false
 git = "https://github.com/paritytech/substrate"
@@ -487,6 +482,7 @@
 pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }
+pallet-identity = { default-features = false, path = "../../pallets/identity" }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
 pallet-structure = { default-features = false, path = "../../pallets/structure" }