Refactoring Checkpoint: (WIP)

This commit is contained in:
2025-12-14 10:29:31 +03:00
parent 09735eb97a
commit c89d7cac55
1424 changed files with 6415 additions and 6064 deletions
@@ -0,0 +1,551 @@
use crate::{mock::*, types::KycLevel, Error, Event};
use pezframe_support::{assert_noop, assert_ok, traits::Currency};
use pezsp_core::H256;
use pezsp_runtime::DispatchError;
// Kolay erişim için paletimize bir takma ad veriyoruz.
type IdentityKycPallet = crate::Pallet<Test>;
// ============================================================================
// Genesis Config Tests
// ============================================================================
#[test]
fn genesis_config_works() {
new_test_ext().execute_with(|| {
// FOUNDER and CITIZEN_1 should be pre-approved via genesis
assert_eq!(IdentityKycPallet::kyc_status_of(FOUNDER), KycLevel::Approved);
assert_eq!(IdentityKycPallet::kyc_status_of(CITIZEN_1), KycLevel::Approved);
// Their identity hashes should be stored
assert!(IdentityKycPallet::identity_hash_of(FOUNDER).is_some());
assert!(IdentityKycPallet::identity_hash_of(CITIZEN_1).is_some());
// Non-founding users should be NotStarted
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::NotStarted);
});
}
// ============================================================================
// apply_for_citizenship Tests
// ============================================================================
#[test]
fn apply_for_citizenship_works() {
new_test_ext().execute_with(|| {
let identity_hash = H256::from_low_u64_be(12345);
// APPLICANT applies with CITIZEN_1 as referrer (who is pre-approved)
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
identity_hash,
CITIZEN_1
));
// Check status changed to PendingReferral
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::PendingReferral);
// Check application was stored
let app = IdentityKycPallet::applications(APPLICANT).expect("Application should exist");
assert_eq!(app.identity_hash, identity_hash);
assert_eq!(app.referrer, CITIZEN_1);
// Check deposit was reserved
assert_eq!(Balances::reserved_balance(APPLICANT), KycApplicationDepositAmount::get());
// Check event was emitted
System::assert_last_event(
Event::CitizenshipApplied { applicant: APPLICANT, referrer: CITIZEN_1, identity_hash }
.into(),
);
});
}
#[test]
fn apply_for_citizenship_fails_if_self_referral() {
new_test_ext().execute_with(|| {
// Cannot refer yourself
assert_noop!(
IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(CITIZEN_1),
H256::from_low_u64_be(999),
CITIZEN_1 // Same as caller
),
Error::<Test>::SelfReferral
);
});
}
#[test]
fn apply_for_citizenship_fails_if_referrer_not_citizen() {
new_test_ext().execute_with(|| {
// APPLICANT is not a citizen, so cannot be a referrer
assert_noop!(
IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(CITIZEN_2),
H256::from_low_u64_be(999),
APPLICANT // Not a citizen
),
Error::<Test>::ReferrerNotCitizen
);
});
}
#[test]
fn apply_for_citizenship_fails_if_already_applied() {
new_test_ext().execute_with(|| {
let identity_hash = H256::from_low_u64_be(12345);
// First application succeeds
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
identity_hash,
CITIZEN_1
));
// Second application fails
assert_noop!(
IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(99999),
CITIZEN_1
),
Error::<Test>::ApplicationAlreadyExists
);
});
}
#[test]
fn apply_for_citizenship_fails_insufficient_balance() {
new_test_ext().execute_with(|| {
let poor_user = 999; // No balance in genesis
assert_noop!(
IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(poor_user),
H256::from_low_u64_be(12345),
CITIZEN_1
),
pezpallet_balances::Error::<Test>::InsufficientBalance
);
});
}
// ============================================================================
// approve_referral Tests
// ============================================================================
#[test]
fn approve_referral_works() {
new_test_ext().execute_with(|| {
let identity_hash = H256::from_low_u64_be(12345);
// APPLICANT applies with CITIZEN_1 as referrer
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
identity_hash,
CITIZEN_1
));
// CITIZEN_1 approves the referral
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
// Check status changed to ReferrerApproved
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::ReferrerApproved);
// Check event
System::assert_last_event(
Event::ReferralApproved { referrer: CITIZEN_1, applicant: APPLICANT }.into(),
);
});
}
#[test]
fn approve_referral_fails_if_not_referrer() {
new_test_ext().execute_with(|| {
// APPLICANT applies with CITIZEN_1 as referrer
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
// FOUNDER (different citizen) cannot approve
assert_noop!(
IdentityKycPallet::approve_referral(RuntimeOrigin::signed(FOUNDER), APPLICANT),
Error::<Test>::NotTheReferrer
);
});
}
#[test]
fn approve_referral_fails_if_not_pending() {
new_test_ext().execute_with(|| {
// Try to approve referral for someone who hasn't applied
assert_noop!(
IdentityKycPallet::approve_referral(RuntimeOrigin::signed(CITIZEN_1), APPLICANT),
Error::<Test>::CannotApproveInCurrentState
);
});
}
// ============================================================================
// confirm_citizenship Tests (Self-confirmation for Welati NFT)
// ============================================================================
#[test]
fn confirm_citizenship_works() {
new_test_ext().execute_with(|| {
let identity_hash = H256::from_low_u64_be(12345);
let initial_balance = Balances::free_balance(APPLICANT);
// Apply
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
identity_hash,
CITIZEN_1
));
// Referrer approves
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
// Self-confirm
assert_ok!(IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)));
// Check status is Approved
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::Approved);
// Check identity hash is stored permanently
assert_eq!(IdentityKycPallet::identity_hash_of(APPLICANT), Some(identity_hash));
// Check referrer is stored permanently
assert_eq!(IdentityKycPallet::citizen_referrer(APPLICANT), Some(CITIZEN_1));
// Check application was removed
assert!(IdentityKycPallet::applications(APPLICANT).is_none());
// Check deposit was returned
assert_eq!(Balances::reserved_balance(APPLICANT), 0);
assert_eq!(Balances::free_balance(APPLICANT), initial_balance);
// Check event
System::assert_last_event(Event::CitizenshipConfirmed { who: APPLICANT }.into());
});
}
#[test]
fn confirm_citizenship_fails_if_not_referrer_approved() {
new_test_ext().execute_with(|| {
// Apply but don't get referrer approval
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
// Try to self-confirm without referrer approval
assert_noop!(
IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)),
Error::<Test>::CannotConfirmInCurrentState
);
});
}
#[test]
fn confirm_citizenship_fails_if_not_applied() {
new_test_ext().execute_with(|| {
// Try to confirm without applying
assert_noop!(
IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)),
Error::<Test>::CannotConfirmInCurrentState
);
});
}
// ============================================================================
// cancel_application Tests
// ============================================================================
#[test]
fn cancel_application_works() {
new_test_ext().execute_with(|| {
let initial_balance = Balances::free_balance(APPLICANT);
// Apply
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
// Deposit should be reserved
assert_eq!(Balances::reserved_balance(APPLICANT), KycApplicationDepositAmount::get());
// Cancel
assert_ok!(IdentityKycPallet::cancel_application(RuntimeOrigin::signed(APPLICANT)));
// Status should be reset to NotStarted
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::NotStarted);
// Application should be removed
assert!(IdentityKycPallet::applications(APPLICANT).is_none());
// Deposit should be returned
assert_eq!(Balances::reserved_balance(APPLICANT), 0);
assert_eq!(Balances::free_balance(APPLICANT), initial_balance);
// Event
System::assert_last_event(Event::ApplicationCancelled { who: APPLICANT }.into());
});
}
#[test]
fn cancel_application_fails_if_not_pending_referral() {
new_test_ext().execute_with(|| {
// Apply and get referrer approval
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
// Cannot cancel after referrer approved (status is ReferrerApproved)
assert_noop!(
IdentityKycPallet::cancel_application(RuntimeOrigin::signed(APPLICANT)),
Error::<Test>::CannotCancelInCurrentState
);
});
}
#[test]
fn cancel_application_allows_reapplication() {
new_test_ext().execute_with(|| {
// First application
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
// Cancel
assert_ok!(IdentityKycPallet::cancel_application(RuntimeOrigin::signed(APPLICANT)));
// Can apply again with different referrer
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(99999),
FOUNDER // Different referrer this time
));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::PendingReferral);
});
}
// ============================================================================
// revoke_citizenship Tests (Governance action)
// ============================================================================
#[test]
fn revoke_citizenship_works() {
new_test_ext().execute_with(|| {
// Complete citizenship flow for APPLICANT
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
assert_ok!(IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::Approved);
// Governance revokes
assert_ok!(IdentityKycPallet::revoke_citizenship(RuntimeOrigin::root(), APPLICANT));
// Status should be Revoked
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::Revoked);
// Event
System::assert_last_event(Event::CitizenshipRevoked { who: APPLICANT }.into());
});
}
#[test]
fn revoke_citizenship_fails_for_bad_origin() {
new_test_ext().execute_with(|| {
// Non-root cannot revoke
assert_noop!(
IdentityKycPallet::revoke_citizenship(RuntimeOrigin::signed(CITIZEN_1), FOUNDER),
DispatchError::BadOrigin
);
});
}
#[test]
fn revoke_citizenship_fails_if_not_citizen() {
new_test_ext().execute_with(|| {
// APPLICANT is not a citizen
assert_noop!(
IdentityKycPallet::revoke_citizenship(RuntimeOrigin::root(), APPLICANT),
Error::<Test>::CannotRevokeInCurrentState
);
});
}
// ============================================================================
// renounce_citizenship Tests (Voluntary exit)
// ============================================================================
#[test]
fn renounce_citizenship_works() {
new_test_ext().execute_with(|| {
// CITIZEN_1 is pre-approved, can renounce
assert_eq!(IdentityKycPallet::kyc_status_of(CITIZEN_1), KycLevel::Approved);
assert_ok!(IdentityKycPallet::renounce_citizenship(RuntimeOrigin::signed(CITIZEN_1)));
// Status should be reset to NotStarted
assert_eq!(IdentityKycPallet::kyc_status_of(CITIZEN_1), KycLevel::NotStarted);
// Identity hash should be removed
assert!(IdentityKycPallet::identity_hash_of(CITIZEN_1).is_none());
// Event
System::assert_last_event(Event::CitizenshipRenounced { who: CITIZEN_1 }.into());
});
}
#[test]
fn renounce_citizenship_fails_if_not_citizen() {
new_test_ext().execute_with(|| {
// APPLICANT is not a citizen
assert_noop!(
IdentityKycPallet::renounce_citizenship(RuntimeOrigin::signed(APPLICANT)),
Error::<Test>::NotACitizen
);
});
}
// ============================================================================
// Full Workflow Tests
// ============================================================================
#[test]
fn full_citizenship_workflow() {
new_test_ext().execute_with(|| {
let identity_hash = H256::from_low_u64_be(12345);
// 1. Apply
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
identity_hash,
CITIZEN_1
));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::PendingReferral);
// 2. Referrer approves
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::ReferrerApproved);
// 3. Self-confirm
assert_ok!(IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::Approved);
// 4. Now APPLICANT is a citizen and can be a referrer for others
let new_user = 50;
// First give new_user some balance
Balances::make_free_balance_be(&new_user, 10_000);
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(new_user),
H256::from_low_u64_be(99999),
APPLICANT // APPLICANT is now the referrer
));
assert_eq!(IdentityKycPallet::kyc_status_of(new_user), KycLevel::PendingReferral);
});
}
#[test]
fn renounce_and_reapply_workflow() {
new_test_ext().execute_with(|| {
// Complete first citizenship
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
assert_ok!(IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::Approved);
// Renounce
assert_ok!(IdentityKycPallet::renounce_citizenship(RuntimeOrigin::signed(APPLICANT)));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::NotStarted);
// Can reapply (free world principle)
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(99999), // Different hash
FOUNDER // Different referrer
));
assert_eq!(IdentityKycPallet::kyc_status_of(APPLICANT), KycLevel::PendingReferral);
});
}
// ============================================================================
// Helper Function Tests
// ============================================================================
#[test]
fn is_citizen_works() {
new_test_ext().execute_with(|| {
// Founding citizens should return true
assert!(IdentityKycPallet::is_citizen(&FOUNDER));
assert!(IdentityKycPallet::is_citizen(&CITIZEN_1));
// Non-citizens should return false
assert!(!IdentityKycPallet::is_citizen(&APPLICANT));
});
}
#[test]
fn get_referrer_works() {
new_test_ext().execute_with(|| {
// Complete citizenship for APPLICANT
assert_ok!(IdentityKycPallet::apply_for_citizenship(
RuntimeOrigin::signed(APPLICANT),
H256::from_low_u64_be(12345),
CITIZEN_1
));
assert_ok!(IdentityKycPallet::approve_referral(
RuntimeOrigin::signed(CITIZEN_1),
APPLICANT
));
assert_ok!(IdentityKycPallet::confirm_citizenship(RuntimeOrigin::signed(APPLICANT)));
// Should return the referrer
assert_eq!(IdentityKycPallet::get_referrer(&APPLICANT), Some(CITIZEN_1));
// Founding citizens have no referrer (they were genesis)
assert_eq!(IdentityKycPallet::get_referrer(&FOUNDER), None);
});
}