// This file is part of Substrate. // Copyright (C) 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::{ self as pallet_identity, legacy::{IdentityField, IdentityInfo}, }; use codec::{Decode, Encode}; use frame_support::{ assert_noop, assert_ok, derive_impl, ord_parameter_types, parameter_types, traits::{ConstU32, ConstU64, EitherOfDiverse, Get}, BoundedVec, }; use frame_system::{EnsureRoot, EnsureSignedBy}; use sp_core::H256; use sp_runtime::{ traits::{BadOrigin, BlakeTwo256, IdentityLookup}, BuildStorage, }; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( pub enum Test { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Identity: pallet_identity::{Pallet, Call, Storage, Event}, } ); #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; 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 = (); type FreezeIdentifier = (); type MaxFreezes = (); type RuntimeHoldReason = (); type RuntimeFreezeReason = (); type MaxHolds = (); } 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, EnsureSignedBy>; type EnsureTwoOrRoot = EitherOfDiverse, EnsureSignedBy>; impl pallet_identity::Config for Test { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type Slashed = (); type BasicDeposit = ConstU64<100>; type ByteDeposit = ConstU64<10>; type SubAccountDeposit = ConstU64<100>; type MaxSubAccounts = ConstU32<2>; type IdentityInformation = IdentityInfo; 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().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(1, 100), (2, 100), (3, 100), (10, 1000), (20, 1000), (30, 1000)], } .assimilate_storage(&mut t) .unwrap(); t.into() } fn ten() -> IdentityInfo { 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 { 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() } } fn id_deposit(id: &IdentityInfo) -> u64 { let base_deposit: u64 = <::BasicDeposit as Get>::get(); let byte_deposit: u64 = <::ByteDeposit as Get>::get() * TryInto::::try_into(id.encoded_size()).unwrap(); base_deposit + byte_deposit } #[test] fn identity_fields_repr_works() { // `IdentityField` sanity checks. assert_eq!(IdentityField::Display as u64, 1 << 0); assert_eq!(IdentityField::Legal as u64, 1 << 1); assert_eq!(IdentityField::Web as u64, 1 << 2); assert_eq!(IdentityField::Riot as u64, 1 << 3); assert_eq!(IdentityField::Email as u64, 1 << 4); assert_eq!(IdentityField::PgpFingerprint as u64, 1 << 5); assert_eq!(IdentityField::Image as u64, 1 << 6); assert_eq!(IdentityField::Twitter as u64, 1 << 7); let fields = IdentityField::Legal | IdentityField::Web | IdentityField::Riot | IdentityField::PgpFingerprint | IdentityField::Twitter; assert!(!fields.contains(IdentityField::Display)); assert!(fields.contains(IdentityField::Legal)); assert!(fields.contains(IdentityField::Web)); assert!(fields.contains(IdentityField::Riot)); assert!(!fields.contains(IdentityField::Email)); assert!(fields.contains(IdentityField::PgpFingerprint)); assert!(!fields.contains(IdentityField::Image)); assert!(fields.contains(IdentityField::Twitter)); // Ensure that the `u64` representation matches what we expect. assert_eq!( fields.bits(), 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10101110 ); } #[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::::NoIdentity ); let ten = ten(); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten.clone()))); let id_deposit = id_deposit(&ten); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); let sub_deposit: u64 = <::SubAccountDeposit as Get>::get(); // first sub account assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 1, data(1))); assert_eq!(SuperOf::::get(1), Some((10, data(1)))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - sub_deposit); // second sub account assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 2, data(2))); assert_eq!(SuperOf::::get(1), Some((10, data(1)))); assert_eq!(SuperOf::::get(2), Some((10, data(2)))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 2 * sub_deposit); // third sub account is too many assert_noop!( Identity::add_sub(RuntimeOrigin::signed(10), 3, data(3)), Error::::TooManySubAccounts ); // rename first sub account assert_ok!(Identity::rename_sub(RuntimeOrigin::signed(10), 1, data(11))); assert_eq!(SuperOf::::get(1), Some((10, data(11)))); assert_eq!(SuperOf::::get(2), Some((10, data(2)))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 2 * sub_deposit); // remove first sub account assert_ok!(Identity::remove_sub(RuntimeOrigin::signed(10), 1)); assert_eq!(SuperOf::::get(1), None); assert_eq!(SuperOf::::get(2), Some((10, data(2)))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - sub_deposit); // add third sub account assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 3, data(3))); assert_eq!(SuperOf::::get(1), None); assert_eq!(SuperOf::::get(2), Some((10, data(2)))); assert_eq!(SuperOf::::get(3), Some((10, data(3)))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 2 * sub_deposit); }); } #[test] fn resolving_subaccount_ownership_works() { new_test_ext().execute_with(|| { let data = |x| Data::Raw(vec![x; 1].try_into().unwrap()); let sub_deposit: u64 = <::SubAccountDeposit as Get>::get(); let ten = ten(); let ten_deposit = id_deposit(&ten); let twenty = twenty(); let twenty_deposit = id_deposit(&twenty); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten))); assert_eq!(Balances::free_balance(10), 1000 - ten_deposit); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(20), Box::new(twenty))); assert_eq!(Balances::free_balance(20), 1000 - twenty_deposit); // 10 claims 1 as a subaccount assert_ok!(Identity::add_sub(RuntimeOrigin::signed(10), 1, data(1))); assert_eq!(Balances::free_balance(1), 100); assert_eq!(Balances::free_balance(10), 1000 - ten_deposit - sub_deposit); assert_eq!(Balances::reserved_balance(10), ten_deposit + sub_deposit); // 20 cannot claim 1 now assert_noop!( Identity::add_sub(RuntimeOrigin::signed(20), 1, data(1)), Error::::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), 100 + sub_deposit); assert_eq!(Balances::free_balance(10), 1000 - ten_deposit - sub_deposit); assert_eq!(Balances::reserved_balance(10), ten_deposit); // 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_invalid_index() { 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 = IdentityField::Display | IdentityField::Legal; assert_noop!( Identity::set_fields(RuntimeOrigin::signed(3), 100, fields.bits()), Error::::InvalidIndex ); }); } #[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 = IdentityField::Display | IdentityField::Legal; assert_ok!(Identity::set_fields(RuntimeOrigin::signed(3), 0, fields.bits())); assert_eq!( Identity::registrars(), vec![Some(RegistrarInfo { account: 3, fee: 10, fields: fields.bits() })] ); }); } #[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::::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()); let ten = ten(); let id_deposit = id_deposit(&ten); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten.clone()))); assert_eq!(Identity::identity(10).unwrap().info, ten); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); assert_ok!(Identity::clear_identity(RuntimeOrigin::signed(10))); assert_eq!(Balances::free_balance(10), 1000); assert_noop!(Identity::clear_identity(RuntimeOrigin::signed(10)), Error::::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::::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::::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::::JudgementForDifferentIdentity ); let identity_hash = BlakeTwo256::hash_of(&ten()); assert_noop!( Identity::provide_judgement( RuntimeOrigin::signed(10), 0, 10, Judgement::Reasonable, identity_hash ), Error::::InvalidIndex ); assert_noop!( Identity::provide_judgement( RuntimeOrigin::signed(3), 0, 10, Judgement::FeePaid(1), identity_hash ), Error::::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(|| { let ten = ten(); let id_deposit = id_deposit(&ten); 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), 1000 - id_deposit); assert_noop!( Identity::kill_identity(RuntimeOrigin::signed(2), 10), Error::::NotNamed ); }); } #[test] fn setting_subaccounts_should_work() { new_test_ext().execute_with(|| { let ten = ten(); let id_deposit = id_deposit(&ten); let sub_deposit: u64 = <::SubAccountDeposit as Get>::get(); let mut subs = vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))]; assert_noop!( Identity::set_subs(RuntimeOrigin::signed(10), subs.clone()), Error::::NotFound ); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); assert_ok!(Identity::set_subs(RuntimeOrigin::signed(10), subs.clone())); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - sub_deposit); assert_eq!(Identity::subs_of(10), (sub_deposit, 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), 1000 - id_deposit - 2 * sub_deposit); assert_eq!(Identity::subs_of(10), (2 * sub_deposit, 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())); // no change in the balance assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 2 * sub_deposit); assert_eq!(Identity::subs_of(10), (2 * sub_deposit, 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), 1000 - id_deposit); 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::::TooManySubAccounts ); }); } #[test] fn clearing_account_should_remove_subaccounts_and_refund() { new_test_ext().execute_with(|| { let ten = ten(); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten.clone()))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit(&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), 1000); assert!(Identity::super_of(20).is_none()); }); } #[test] fn killing_account_should_remove_subaccounts_and_not_refund() { new_test_ext().execute_with(|| { let ten = ten(); let id_deposit = id_deposit(&ten); let sub_deposit: u64 = <::SubAccountDeposit as Get>::get(); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); assert_ok!(Identity::set_subs( RuntimeOrigin::signed(10), vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))] )); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - sub_deposit); assert_ok!(Identity::kill_identity(RuntimeOrigin::signed(2), 10)); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - sub_deposit); 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::::NoIdentity ); let ten = ten(); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten.clone()))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit(&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), 1000 - id_deposit(&ten)); assert_noop!( Identity::cancel_request(RuntimeOrigin::signed(10), 0), Error::::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::::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)); let ten = ten(); let id_deposit = id_deposit(&ten); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten.clone()))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); assert_noop!( Identity::request_judgement(RuntimeOrigin::signed(10), 0, 9), Error::::FeeChanged ); assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10)); // 10 for the judgement request and the deposit for the identity. assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 10); // Re-requesting won't work as we already paid. assert_noop!( Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10), Error::::StickyJudgement ); assert_ok!(Identity::provide_judgement( RuntimeOrigin::signed(3), 0, 10, Judgement::Erroneous, BlakeTwo256::hash_of(&ten) )); // Registrar got their payment now. // 100 initial balance and 10 for the judgement. assert_eq!(Balances::free_balance(3), 100 + 10); // Re-requesting still won't work as it's erroneous. assert_noop!( Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10), Error::::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(|| { let ten = ten(); let id_deposit = id_deposit(&ten); 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.clone()))); assert_ok!(Identity::request_judgement(RuntimeOrigin::signed(10), 0, 10)); // 10 for the judgement request and the deposit for the identity. assert_eq!(Balances::free_balance(10), 1000 - id_deposit - 10); // 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::::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)); let id = 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() }; let id_deposit = id_deposit(&id); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(id))); assert_eq!(Balances::free_balance(10), 1000 - id_deposit); }); } #[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::::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 )); }); } #[test] fn reap_identity_works() { new_test_ext().execute_with(|| { let ten_info = ten(); assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten_info.clone()))); assert_ok!(Identity::set_subs( RuntimeOrigin::signed(10), vec![(20, Data::Raw(vec![40; 1].try_into().unwrap()))] )); // deposit is correct let id_deposit = id_deposit(&ten_info); let subs_deposit: u64 = <::SubAccountDeposit as Get>::get(); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - subs_deposit); // reap assert_ok!(Identity::reap_identity(&10)); // no identity or subs assert!(Identity::identity(10).is_none()); assert!(Identity::super_of(20).is_none()); // balance is unreserved assert_eq!(Balances::free_balance(10), 1000); }); } #[test] fn poke_deposit_works() { new_test_ext().execute_with(|| { let ten_info = ten(); // Set a custom registration with 0 deposit IdentityOf::::insert( &10, Registration { judgements: BoundedVec::default(), deposit: Zero::zero(), info: ten_info.clone(), }, ); assert!(Identity::identity(10).is_some()); // Set a sub with zero deposit SubsOf::::insert::<&u64, (u64, BoundedVec>)>( &10, (0, vec![20].try_into().unwrap()), ); SuperOf::::insert(&20, (&10, Data::Raw(vec![1; 1].try_into().unwrap()))); // Balance is free assert_eq!(Balances::free_balance(10), 1000); // poke assert_ok!(Identity::poke_deposit(&10)); // free balance reduced correctly let id_deposit = id_deposit(&ten_info); let subs_deposit: u64 = <::SubAccountDeposit as Get>::get(); assert_eq!(Balances::free_balance(10), 1000 - id_deposit - subs_deposit); // new registration deposit is 10 assert_eq!( Identity::identity(&10), Some(Registration { judgements: BoundedVec::default(), deposit: id_deposit, info: ten() }) ); // new subs deposit is 10 vvvvvvvvvvvv assert_eq!(Identity::subs_of(10), (subs_deposit, vec![20].try_into().unwrap())); }); }