Skip to content
Snippets Groups Projects
Select Git revision
  • 74dadb8c545738bfa7b815b98c1121632c04f05a
  • master default protected
  • 313_ci_image
  • 311_gtest_fixes
  • set_UniversalDividendApi_in_RuntimeApiCollection
  • tuxmain/fix-change-owner-key
  • network/gtest-1000 protected
  • upgradable-multisig
  • runtime/gtest-1000
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • gtest-1000-0.11.1 protected
  • gtest-1000-0.11.0 protected
  • gtest-1000 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
41 results

integration_tests.rs

Blame
  • integration_tests.rs 34.61 KiB
    // Copyright 2021 Axiom-Team
    //
    // This file is part of Duniter-v2S.
    //
    // Duniter-v2S is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, version 3 of the License.
    //
    // Duniter-v2S 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 Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
    
    extern crate core;
    
    use frame_support::traits::{Get, PalletInfo, StorageInfo, StorageInfoTrait};
    use frame_support::{assert_noop, assert_ok};
    use frame_support::{StorageHasher, Twox128};
    use sp_keyring::AccountKeyring;
    use sp_runtime::MultiAddress;
    
    use common::*;
    use gdev_runtime::*;
    
    use crate::common::golden_testing::iterative::StorageIterativeChecker;
    
    mod common;
    
    #[test]
    fn verify_treasury_account() {
        // println!("{}", Treasury::account_id());
    }
    
    #[test]
    fn values_storage_with_run_to_block() {
        let mut externalities = ExtBuilder::new(1, 3, 4).build();
        let mut storage_checker = StorageIterativeChecker::new_default(|| Runtime::metadata().1);
        externalities.execute_with(|| {
            run_to_block(2);
            storage_checker.test_storage(128);
            //         run_to_block(3);
            //         storage_checker.change_expected(Box::new(|| Key::SystemNumber(3)));
            //         storage_checker.test_storage(128);
            //
            //         // alice create identity for Eve
            //         assert_ok!(Identity::create_identity(
            //             frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
            //             AccountKeyring::Eve.to_account_id(),
            //         ));
            //         run_to_block(4);
            //
            //         // Creating an identity changes the following fields
            //         storage_checker.change_expected(Box::new(|| Key::SystemNumber(4))); // +1
            //         storage_checker.change_expected(Box::new(|| Key::IdentityCounterForIdentities(5))); // +1
            //         storage_checker.change_expected(Box::new(|| Key::IdentityNextIdtyIndex(6))); // +1
            //         storage_checker.change_expected(Box::new(|| {
            //             Key::IdentityIdentities(btreemap!(
            //                 1 => IdtyValue {
            //                     data: IdtyData {
            //                         first_eligible_ud: FirstEligibleUd::from(1),
            //                     },
            //                     next_creatable_identity_on: 53, // Changed
            //                     old_owner_key: None,
            //                     owner_key: get_account_id_from_seed::<sr25519::Public>("Alice"),
            //                     removable_on: 0,
            //                     status: IdtyStatus::Validated,
            //                 },
            //                 // New identity!
            //                 5 => IdtyValue {
            //                     data: IdtyData {
            //                         first_eligible_ud: FirstEligibleUd(None),
            //                     },
            //                     next_creatable_identity_on: 0,
            //                     old_owner_key: None,
            //                     owner_key: get_account_id_from_seed::<sr25519::Public>("Eve"),
            //                     removable_on: 43, // Removable because not validated
            //                     status: IdtyStatus::Created,
            //                 }
            //             ))
            //         }));
            //         // Adds e659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e in System.Account
            //         storage_checker.change_expected(Box::new(|| Key::_ManualKey("System".to_string(), "Account".to_string(), "[
            // 	306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20 (5DAAnrj7...) = AccountInfo { nonce: 0, consumers: 0, providers: 0, sufficients: 1, data: AccountData { random_id: Some(0x0303030303030303030303030303030303030303030303030303030303030303), free: 0, reserved: 0, fee_frozen: 0 } }
            // 	6d6f646c70792f74727372790000000000000000000000000000000000000000 (5EYCAe5i...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 0, data: AccountData { random_id: None, free: 200, reserved: 0, fee_frozen: 0 } }
            // 	8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0101010101010101010101010101010101010101010101010101010101010101), free: 0, reserved: 0, fee_frozen: 0 } }
            // 	90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0202020202020202020202020202020202020202020202020202020202020202), free: 0, reserved: 0, fee_frozen: 0 } }
            // 	d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0000000000000000000000000000000000000000000000000000000000000000), free: 0, reserved: 0, fee_frozen: 0 } }
            // 	e659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e (5HGjWAeF...) = AccountInfo { nonce: 0, consumers: 0, providers: 0, sufficients: 1, data: AccountData { random_id: None, free: 0, reserved: 0, fee_frozen: 0 } }
            // ]".to_string())));
            //         storage_checker.test_storage(128);
            //
            //         // eve confirms her identity
            //         assert_ok!(Identity::confirm_identity(
            //             frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
            //             "Eeeeeveeeee".into(),
            //         ));
            //
            //         run_to_block(5);
            //
            //         // Creating an identity changes the following fields
            //         storage_checker.change_expected(Box::new(|| Key::SystemNumber(5))); // +1
            //         storage_checker.change_expected(Box::new(|| Key::IdentityCounterForIdentities(5))); // +1
            //         storage_checker.change_expected(Box::new(|| Key::IdentityNextIdtyIndex(6))); // +1
            //         storage_checker.change_expected(Box::new(|| {
            //             Key::IdentityIdentitiesNames(btreemap!(
            //                 "Alice".into() => (),
            //                 "Bob".into() => (),
            //                 "Charlie".into() => (),
            //                 "Dave".into() => (),
            //                 "Eeeeeveeeee".into() => ()
            //             ))
            //         }));
            //         storage_checker.change_expected(Box::new(|| {
            //             Key::IdentityIdentities(btreemap!(
            //                 1 => IdtyValue {
            //                     data: IdtyData {
            //                         first_eligible_ud: FirstEligibleUd::from(1),
            //                     },
            //                     next_creatable_identity_on: 53,
            //                     old_owner_key: None,
            //                     owner_key: get_account_id_from_seed::<sr25519::Public>("Alice"),
            //                     removable_on: 0,
            //                     status: IdtyStatus::Validated,
            //                 },
            //                 5 => IdtyValue {
            //                     data: IdtyData {
            //                         first_eligible_ud: FirstEligibleUd(None),
            //                     },
            //                     next_creatable_identity_on: 0,
            //                     old_owner_key: None,
            //                     owner_key: get_account_id_from_seed::<sr25519::Public>("Eve"),
            //                     removable_on: 43,
            //                     status: IdtyStatus::ConfirmedByOwner, // <-- changed
            //                 }
            //             ))
            //         }));
            //         storage_checker.test_storage(128);
        });
        storage_checker.test_well_known_keys(&mut externalities);
    }
    
    #[test]
    fn verify_pallet_prefixes() {
        let prefix = |pallet_name, storage_name| {
            let mut res = [0u8; 32];
            res[0..16].copy_from_slice(&Twox128::hash(pallet_name));
            res[16..32].copy_from_slice(&Twox128::hash(storage_name));
            res.to_vec()
        };
        assert_eq!(
            <Timestamp as StorageInfoTrait>::storage_info(),
            vec![
                StorageInfo {
                    pallet_name: b"Timestamp".to_vec(),
                    storage_name: b"Now".to_vec(),
                    prefix: prefix(b"Timestamp", b"Now"),
                    max_values: Some(1),
                    max_size: Some(8),
                },
                StorageInfo {
                    pallet_name: b"Timestamp".to_vec(),
                    storage_name: b"DidUpdate".to_vec(),
                    prefix: prefix(b"Timestamp", b"DidUpdate"),
                    max_values: Some(1),
                    max_size: Some(1),
                }
            ]
        );
    }
    
    #[test]
    fn verify_pallet_indices() {
        fn is_pallet_index<P: 'static>(index: usize) {
            assert_eq!(
                <Runtime as frame_system::Config>::PalletInfo::index::<P>(),
                Some(index)
            );
        }
        is_pallet_index::<System>(0);
    }
    
    #[test]
    fn verify_proxy_type_indices() {
        assert_eq!(ProxyType::AlmostAny as u8, 0);
    }
    
    #[test]
    fn test_genesis_build() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            run_to_block(2);
        });
    }
    
    /// test calling remove_identity
    #[test]
    fn test_remove_identity() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            run_to_block(2);
    
            assert_ok!(Identity::remove_identity(
                frame_system::RawOrigin::Root.into(),
                4,
                None
            ));
    
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipRevoked(4),
            ));
            System::assert_has_event(RuntimeEvent::System(frame_system::Event::KilledAccount {
                account: AccountKeyring::Dave.to_account_id(),
            }));
            System::assert_has_event(RuntimeEvent::Identity(
                pallet_identity::Event::IdtyRemoved { idty_index: 4 },
            ));
        });
    }
    
    /// test identity is validated when membership is claimed
    #[test]
    fn test_validate_identity_when_claim() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![(AccountKeyring::Ferdie.to_account_id(), 1000)])
            .build()
            .execute_with(|| {
                run_to_block(1);
                // alice create identity for Eve
                assert_ok!(Identity::create_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    AccountKeyring::Eve.to_account_id(),
                ));
                run_to_block(2);
                // eve confirms her identity
                assert_ok!(Identity::confirm_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                    "Eeeeeveeeee".into(),
                ));
                run_to_block(3);
                // eve gets certified by bob and charlie
                assert_ok!(Cert::add_cert(
                    frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(),
                    2,
                    5
                ));
                assert_ok!(Cert::add_cert(
                    frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(),
                    3,
                    5
                ));
    
                // eve can claim her membership
                assert_ok!(Membership::claim_membership(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                ));
    
                System::assert_has_event(RuntimeEvent::Membership(
                    pallet_membership::Event::MembershipAcquired(5),
                ));
    
                // ferdie can not validate eve identity because already validated
                assert_noop!(
                    Identity::validate_identity(
                        frame_system::RawOrigin::Signed(AccountKeyring::Ferdie.to_account_id()).into(),
                        5,
                    ),
                    pallet_identity::Error::<Runtime>::IdtyAlreadyValidated
                );
            });
    }
    
    /// test membership expiry
    #[test]
    fn test_membership_expiry() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            run_to_block(100);
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipExpired(1),
            ));
            // membership expiry should not trigger identity removal
            assert!(!System::events().iter().any(|record| record.event
                == RuntimeEvent::Identity(pallet_identity::Event::IdtyRemoved { idty_index: 1 })));
        });
    }
    
    /// test membership renewal
    #[test]
    fn test_membership_renewal() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            // renew at block 2
            run_to_block(2);
            assert_ok!(Membership::renew_membership(
                frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
            ));
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipRenewed(1),
            ));
    
            // renew at block 3
            run_to_block(3);
            assert_ok!(Membership::renew_membership(
                frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
            ));
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipRenewed(1),
            ));
    
            // should expire at block 103 = 3+100
            run_to_block(103);
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipExpired(1),
            ));
        });
    }
    
    // test that UD are auto claimed when identity is removed
    #[test]
    fn test_remove_identity_after_one_ud() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            //println!("UdCreationPeriod={}", <Runtime as pallet_universal_dividend::Config>::UdCreationPeriod::get());
            run_to_block(<Runtime as pallet_universal_dividend::Config>::UdCreationPeriod::get() + 1);
    
            assert_ok!(Identity::remove_identity(
                frame_system::RawOrigin::Root.into(),
                4,
                None
            ));
    
            // Verify events
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipRevoked(4),
            ));
            System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Deposit {
                who: AccountKeyring::Dave.to_account_id(),
                amount: 1_000,
            }));
            System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Endowed {
                account: AccountKeyring::Dave.to_account_id(),
                free_balance: 1_000,
            }));
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::UdsAutoPaidAtRemoval {
                    count: 1,
                    total: 1_000,
                    who: AccountKeyring::Dave.to_account_id(),
                },
            ));
            System::assert_has_event(RuntimeEvent::Identity(
                pallet_identity::Event::IdtyRemoved { idty_index: 4 },
            ));
    
            // Verify state
            assert!(Identity::identity(4).is_none());
            assert_eq!(
                Balances::free_balance(AccountKeyring::Dave.to_account_id()),
                1_000
            );
        });
    }
    
    /// test that UD are auto claimed when membership expires
    /// and that claimed UD matches expectations
    #[test]
    fn test_ud_claimed_membership_on_and_off() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            // UD are created every 10 blocks from block 0
            run_to_block(10);
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::NewUdCreated {
                    amount: 1000,
                    index: 1,
                    monetary_mass: 4000,
                    members_count: 4,
                },
            ));
            // UD not claimed, still initial balance to 0
            assert_eq!(
                Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                0
            );
    
            run_to_block(11);
            // alice identity expires
            assert_ok!(Membership::force_expire_membership(1));
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::UdsAutoPaidAtRemoval {
                    count: 1,
                    total: 1_000,
                    who: AccountKeyring::Alice.to_account_id(),
                },
            ));
            // alice balances should be increased by 1 UD
            assert_eq!(
                Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                1000
            );
    
            // UD number 2
            run_to_block(20);
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::NewUdCreated {
                    amount: 1000,
                    index: 2,
                    monetary_mass: 7000, // 4000 + 3 × 1000
                    members_count: 3,    // alice is not member at this UD
                },
            ));
    
            // alice claims back her membership
            assert_ok!(Membership::claim_membership(
                frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into()
            ));
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipAcquired(1),
            ));
    
            // UD number 3
            run_to_block(30);
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::NewUdCreated {
                    amount: 1000,
                    index: 3,
                    monetary_mass: 11000, // 7000 + 4 × 1000
                    members_count: 4,     // alice is member again at this UD
                },
            ));
    
            // one block later, alice claims her new UD
            run_to_block(31);
            assert_ok!(UniversalDividend::claim_uds(
                frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into()
            ));
            System::assert_has_event(RuntimeEvent::UniversalDividend(
                pallet_universal_dividend::Event::UdsClaimed {
                    count: 1,
                    total: 1_000,
                    who: AccountKeyring::Alice.to_account_id(),
                },
            ));
            assert_eq!(
                Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                2000 // one more UD
            );
    
            // println!("{:?}", System::events());
        });
    }
    
    /// test when root removes and identity, all consumers should be deleted
    #[test]
    fn test_remove_smith_identity() {
        ExtBuilder::new(1, 3, 4).build().execute_with(|| {
            run_to_block(2);
    
            assert_ok!(Identity::remove_identity(
                frame_system::RawOrigin::Root.into(),
                3,
                None
            ));
            // Verify events
            System::assert_has_event(RuntimeEvent::SmithMembership(
                pallet_membership::Event::MembershipRevoked(3),
            ));
            System::assert_has_event(RuntimeEvent::AuthorityMembers(
                pallet_authority_members::Event::MemberRemoved(3),
            ));
            System::assert_has_event(RuntimeEvent::Membership(
                pallet_membership::Event::MembershipRevoked(3),
            ));
            System::assert_has_event(RuntimeEvent::Identity(
                pallet_identity::Event::IdtyRemoved { idty_index: 3 },
            ));
        });
    }
    
    #[test]
    fn test_create_new_account_with_insufficient_balance() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![(AccountKeyring::Alice.to_account_id(), 1_000)])
            .build()
            .execute_with(|| {
                run_to_block(2);
    
                // Should be able to transfer 4 units to a new account
                assert_ok!(Balances::transfer(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    400
                ));
    
                System::assert_has_event(RuntimeEvent::System(frame_system::Event::NewAccount {
                    account: AccountKeyring::Eve.to_account_id(),
                }));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Endowed {
                    account: AccountKeyring::Eve.to_account_id(),
                    free_balance: 400,
                }));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Transfer {
                    from: AccountKeyring::Alice.to_account_id(),
                    to: AccountKeyring::Eve.to_account_id(),
                    amount: 400,
                }));
    
                // At next block, the new account must be reaped because its balance is not sufficient
                // to pay the "new account tax"
                run_to_block(3);
    
                System::assert_has_event(RuntimeEvent::Account(
                    pallet_duniter_account::Event::ForceDestroy {
                        who: AccountKeyring::Eve.to_account_id(),
                        balance: 400,
                    },
                ));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Deposit {
                    who: Treasury::account_id(),
                    amount: 400,
                }));
                System::assert_has_event(RuntimeEvent::Treasury(pallet_treasury::Event::Deposit {
                    value: 400,
                }));
    
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                    0
                );
                assert_eq!(Balances::free_balance(Treasury::account_id()), 600);
            });
    }
    
    #[test]
    fn test_create_new_account() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![(AccountKeyring::Alice.to_account_id(), 1_000)])
            .build()
            .execute_with(|| {
                run_to_block(2);
    
                // Should be able to transfer 5 units to a new account
                assert_ok!(Balances::transfer(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    500
                ));
                //println!("{:#?}", System::events());
                System::assert_has_event(RuntimeEvent::System(frame_system::Event::NewAccount {
                    account: AccountKeyring::Eve.to_account_id(),
                }));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Endowed {
                    account: AccountKeyring::Eve.to_account_id(),
                    free_balance: 500,
                }));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Transfer {
                    from: AccountKeyring::Alice.to_account_id(),
                    to: AccountKeyring::Eve.to_account_id(),
                    amount: 500,
                }));
    
                // At next block, the new account must be created,
                // and new account tax should be collected and deposited in the treasury
                run_to_block(3);
    
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Withdraw {
                    who: AccountKeyring::Eve.to_account_id(),
                    amount: 300,
                }));
                System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Deposit {
                    who: Treasury::account_id(),
                    amount: 300,
                }));
                System::assert_has_event(RuntimeEvent::Treasury(pallet_treasury::Event::Deposit {
                    value: 300,
                }));
    
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                    200
                );
                assert_eq!(Balances::free_balance(Treasury::account_id()), 500);
    
                // A random id request should be registered
                assert_eq!(
                    Account::pending_random_id_assignments(0),
                    Some(AccountKeyring::Eve.to_account_id())
                );
    
                // We can't remove the account until the random id is assigned
                run_to_block(4);
                assert_noop!(
                    Balances::transfer(
                        frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                        MultiAddress::Id(AccountKeyring::Alice.to_account_id()),
                        200
                    ),
                    pallet_balances::Error::<Runtime>::KeepAlive,
                );
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                    200
                );
                assert_ok!(Balances::transfer_all(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Alice.to_account_id()),
                    false
                ),);
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                    200
                );
            });
    }
    
    #[test]
    fn test_create_new_idty() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![(AccountKeyring::Alice.to_account_id(), 1_000)])
            .build()
            .execute_with(|| {
                run_to_block(2);
    
                // Should be able to create an identity
                assert_ok!(Balances::transfer(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    200
                ));
                assert_ok!(Identity::create_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    AccountKeyring::Eve.to_account_id(),
                ));
    
                // At next block, nothing should be preleved
                run_to_block(3);
                let events = System::events();
                assert_eq!(events.len(), 0);
    
                // A random id request should be registered
                assert_eq!(
                    Account::pending_random_id_assignments(0),
                    Some(AccountKeyring::Eve.to_account_id())
                );
            });
    }
    
    #[test]
    fn test_create_new_idty_without_founds() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![(AccountKeyring::Alice.to_account_id(), 1_000)])
            .build()
            .execute_with(|| {
                run_to_block(2);
    
                // Should be able to create an identity without founds
                assert_ok!(Identity::create_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    AccountKeyring::Eve.to_account_id(),
                ));
    
                // At next block, nothing should be preleved
                run_to_block(3);
                let events = System::events();
                assert_eq!(events.len(), 0);
    
                // Deposit some founds on the identity account,
                // this should trigger the random id assignemt
                assert_ok!(Balances::transfer(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    200
                ));
    
                // At next block, nothing should be preleved,
                // and a random id request should be registered
                run_to_block(4);
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                    200
                );
                assert_eq!(
                    Account::pending_random_id_assignments(0),
                    Some(AccountKeyring::Eve.to_account_id())
                );
            });
    }
    
    /// test that newly validated identity gets initialized with the next UD
    #[test]
    fn test_validate_new_idty_after_few_uds() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (AccountKeyring::Alice.to_account_id(), 1_000),
                (AccountKeyring::Bob.to_account_id(), 1_000),
                (AccountKeyring::Charlie.to_account_id(), 1_000),
                (AccountKeyring::Eve.to_account_id(), 1_000),
            ])
            .build()
            .execute_with(|| {
                run_to_block(21);
    
                // Should be able to create an identity
                assert_ok!(Balances::transfer(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    200
                ));
                assert_ok!(Identity::create_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    AccountKeyring::Eve.to_account_id(),
                ));
    
                // At next block, the created identity should be confirmed by its owner
                run_to_block(22);
                assert_ok!(Identity::confirm_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                    pallet_identity::IdtyName::from("Eve"),
                ));
    
                // At next block, Bob should be able to certify and validate the new identity
                run_to_block(23);
                assert_ok!(Cert::add_cert(
                    frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(),
                    2,
                    5,
                ));
                assert_ok!(Identity::validate_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(),
                    5,
                ));
    
                // The new member should have first_eligible_ud equal to three
                assert!(Identity::identity(5).is_some());
                assert_eq!(
                    Identity::identity(5).unwrap().data,
                    IdtyData {
                        // first eligible UD will be at block 30
                        first_eligible_ud: pallet_universal_dividend::FirstEligibleUd::from(3),
                    }
                );
            });
    }
    
    /// test that newly validated identity gets initialized with the next UD
    // even when the method used is membership claim
    #[test]
    fn test_claim_memberhsip_after_few_uds() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (AccountKeyring::Alice.to_account_id(), 1_000),
                (AccountKeyring::Bob.to_account_id(), 1_000),
                (AccountKeyring::Charlie.to_account_id(), 1_000),
                (AccountKeyring::Eve.to_account_id(), 1_000),
            ])
            .build()
            .execute_with(|| {
                run_to_block(21);
    
                // Should be able to create an identity
                assert_ok!(Identity::create_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    AccountKeyring::Eve.to_account_id(),
                ));
    
                // At next block, the created identity should be confirmed by its owner
                run_to_block(22);
                assert_ok!(Identity::confirm_identity(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                    pallet_identity::IdtyName::from("Eve"),
                ));
    
                // At next block, Bob should be able to certify the new identity
                run_to_block(23);
                assert_ok!(Cert::add_cert(
                    frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(),
                    2,
                    5,
                ));
    
                // eve should be able to claim her membership
                assert_ok!(Membership::claim_membership(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                ));
    
                // The new member should have first_eligible_ud equal to three
                assert!(Identity::identity(5).is_some());
                assert_eq!(
                    Identity::identity(5).unwrap().data,
                    IdtyData {
                        // first eligible UD will be at block 30
                        first_eligible_ud: pallet_universal_dividend::FirstEligibleUd::from(3),
                    }
                );
            });
    }
    
    /// test oneshot accounts
    #[test]
    fn test_oneshot_accounts() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (AccountKeyring::Alice.to_account_id(), 1_000),
                (AccountKeyring::Eve.to_account_id(), 1_000),
            ])
            .build()
            .execute_with(|| {
                run_to_block(6);
    
                assert_ok!(OneshotAccount::create_oneshot_account(
                    frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                    MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                    400
                ));
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                    600
                );
                run_to_block(7);
    
                assert_ok!(OneshotAccount::consume_oneshot_account_with_remaining(
                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                    0,
                    pallet_oneshot_account::Account::Oneshot(MultiAddress::Id(
                        AccountKeyring::Ferdie.to_account_id()
                    )),
                    pallet_oneshot_account::Account::Normal(MultiAddress::Id(
                        AccountKeyring::Alice.to_account_id()
                    )),
                    300
                ));
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                    700
                );
                assert_noop!(
                    OneshotAccount::consume_oneshot_account(
                        frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                        0,
                        pallet_oneshot_account::Account::Oneshot(MultiAddress::Id(
                            AccountKeyring::Ferdie.to_account_id()
                        )),
                    ),
                    pallet_oneshot_account::Error::<Runtime>::OneshotAccountNotExist
                );
                run_to_block(8);
                // Oneshot account consumption should not increment the nonce
                assert_eq!(
                    System::account(AccountKeyring::Eve.to_account_id()).nonce,
                    0
                );
    
                assert_ok!(OneshotAccount::consume_oneshot_account(
                    frame_system::RawOrigin::Signed(AccountKeyring::Ferdie.to_account_id()).into(),
                    0,
                    pallet_oneshot_account::Account::Normal(MultiAddress::Id(
                        AccountKeyring::Alice.to_account_id()
                    )),
                ));
                assert_eq!(
                    Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                    1000
                );
                assert_noop!(
                    OneshotAccount::consume_oneshot_account(
                        frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
                        0,
                        pallet_oneshot_account::Account::Normal(MultiAddress::Id(
                            AccountKeyring::Alice.to_account_id()
                        )),
                    ),
                    pallet_oneshot_account::Error::<Runtime>::OneshotAccountNotExist
                );
            });
    }