diff --git a/Cargo.lock b/Cargo.lock index 7060dfa6..280e37de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1400,6 +1400,26 @@ dependencies = [ "syn", ] +[[package]] +name = "enumflags2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.9.0" @@ -1875,6 +1895,7 @@ dependencies = [ "pallet-finalizer", "pallet-grandpa", "pallet-housing_fund", + "pallet-identity", "pallet-nft", "pallet-onboarding", "pallet-preimage", @@ -4246,6 +4267,22 @@ dependencies = [ "sp-std 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.29)", ] +[[package]] +name = "pallet-identity" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.29#cc370aa61e15c18d23a2f686b812fd576a630afe" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.29)", +] + [[package]] name = "pallet-nft" version = "4.0.0" diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 440d3427..5f1362ab 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,6 +1,7 @@ use fs_node_runtime::{ - AccountId, AuraConfig, pallet_roles, BalancesConfig, CouncilConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, - SystemConfig,RoleModuleConfig, NftModuleConfig, WASM_BINARY, + pallet_roles, AccountId, AuraConfig, BalancesConfig, CouncilConfig, GenesisConfig, + GrandpaConfig, NftModuleConfig, RoleModuleConfig, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -156,9 +157,13 @@ fn testnet_genesis( key: Some(root_key), }, transaction_payment: Default::default(), - + role_module: RoleModuleConfig { new_admin: Some(get_account_id_from_seed::("Alice")), + representatives: vec![ + get_account_id_from_seed::("Gabriel"), + get_account_id_from_seed::("Henry"), + ], }, nft_module: NftModuleConfig { owner: Some(get_account_id_from_seed::("Alice")), diff --git a/pallets/asset_management/src/functions.rs b/pallets/asset_management/src/functions.rs index ea6cef33..e043fbde 100644 --- a/pallets/asset_management/src/functions.rs +++ b/pallets/asset_management/src/functions.rs @@ -1,18 +1,18 @@ //Helper functions that will be used in proposal's calls -//helper 1) get shares/owners from asset_id +//helper 1) get shares/owners from asset_id pub use super::*; pub use scale_info::prelude::boxed::Box; pub use frame_support::pallet_prelude::*; pub use sp_core::H256; impl Pallet { - pub fn approve_representative(caller: T::AccountId, who:T::AccountId) -> DispatchResult{ - let mut representative = Roles::Pallet::::get_pending_representatives(&who).unwrap(); - representative.activated = true; - representative.assets_accounts.push(caller); - Roles::RepresentativeLog::::insert(&who,representative); - Roles::RepApprovalList::::remove(&who); - Roles::AccountsRolesLog::::insert(&who, Roles::Accounts::REPRESENTATIVE); + pub fn approve_representative(caller: T::AccountId, who: T::AccountId) -> DispatchResult { + let mut representative = Roles::Pallet::::get_pending_representatives(&who).unwrap(); + representative.activated = true; + representative.assets_accounts.push(caller); + Roles::RepresentativeLog::::insert(&who, representative); + Roles::RepApprovalList::::remove(&who); + Roles::AccountsRolesLog::::insert(&who, Roles::Accounts::REPRESENTATIVE); Ok(()) } diff --git a/pallets/asset_management/src/lib.rs b/pallets/asset_management/src/lib.rs index e06a6502..2a626551 100644 --- a/pallets/asset_management/src/lib.rs +++ b/pallets/asset_management/src/lib.rs @@ -1,12 +1,19 @@ #![cfg_attr(not(feature = "std"), no_std)] +//Pallets needed: +//- Roles for the Representative role +//- Democracy for the voting system +//- Share_Distributor for the conviction weight calculation based on asset shares + +//Needed calls: +//Call 1) Create a Representative role pub use pallet::*; -pub use pallet_roles as Roles; pub use pallet_democracy as Dem; -pub use pallet_share_distributor as Share; +pub use pallet_housing_fund as HFund; pub use pallet_nft as Nft; pub use pallet_onboarding as Onboarding; -pub use pallet_housing_fund as HFund; +pub use pallet_roles as Roles; +pub use pallet_share_distributor as Share; mod functions; mod types; @@ -35,7 +42,15 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config + HFund::Config + Onboarding::Config +Roles::Config + Dem::Config + Share::Config + Nft::Config{ + pub trait Config: + frame_system::Config + + HFund::Config + + Onboarding::Config + + Roles::Config + + Dem::Config + + Share::Config + + Nft::Config + { /// Because this pallet emits events, it depends on the runtime's definition of an event. type Event: From> + IsType<::Event>; type Call: Parameter @@ -153,7 +168,11 @@ pub mod pallet { pub fn representative_approval(origin: OriginFor, rep_account: T::AccountId,collection: T::NftCollectionId,item: T::NftItemId) -> DispatchResult { let caller = ensure_signed(origin)?; //Check that the caller is a stored virtual account - ensure!(caller == Share::Pallet::::virtual_acc(collection,item).unwrap().virtual_account, Error::::NotAnAssetAccount); + ensure!( + caller == + Share::Pallet::::virtual_acc(collection, item).unwrap().virtual_account, + Error::::NotAnAssetAccount + ); //Check that the account is in the representative waiting list ensure!(Roles::Pallet::::get_pending_representatives(&rep_account).is_some(),"problem"); //Approve role request @@ -161,7 +180,5 @@ pub mod pallet { Ok(()) } - - } } diff --git a/pallets/asset_management/src/mock.rs b/pallets/asset_management/src/mock.rs index c851a9b7..1f7b9dde 100644 --- a/pallets/asset_management/src/mock.rs +++ b/pallets/asset_management/src/mock.rs @@ -39,7 +39,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Storage, Event}, - AssetManagement: pallet_asset_management::{Pallet, Call, Storage, Event}, + AssetManagement: pallet_asset_management::{Pallet, Call, Storage, Event}, OnboardingModule: pallet_onboarding::{Pallet, Call, Storage, Event}, VotingModule: pallet_voting::{Pallet, Call, Storage, Event}, RoleModule: pallet_roles::{Pallet, Call, Storage, Event}, diff --git a/pallets/asset_management/src/tests.rs b/pallets/asset_management/src/tests.rs index 9476aca6..667da22f 100644 --- a/pallets/asset_management/src/tests.rs +++ b/pallets/asset_management/src/tests.rs @@ -3,7 +3,6 @@ pub use crate::mock::*; pub use frame_support::{assert_noop, assert_ok}; use frame_system::pallet_prelude::OriginFor; - pub type Bvec = BoundedVec::StringLimit>; pub fn prep_roles() { @@ -12,19 +11,19 @@ pub fn prep_roles() { RoleModule::set_role(Origin::signed(BOB), BOB, Acc::SELLER).ok(); RoleModule::account_approval(Origin::signed(ALICE), BOB).ok(); RoleModule::set_role(Origin::signed(DAVE), DAVE, Acc::INVESTOR).ok(); - RoleModule::set_role(Origin::signed(EVE), EVE, Acc::INVESTOR).ok(); - RoleModule::set_role(Origin::signed(FERDIE), FERDIE, Acc::REPRESENTATIVE).ok();//FERDIE approval will be tested - + RoleModule::set_role(Origin::signed(EVE), EVE, Acc::INVESTOR).ok(); + RoleModule::set_role(Origin::signed(FERDIE), FERDIE, Acc::REPRESENTATIVE).ok(); //FERDIE approval + // will be tested } #[test] -fn representative(){ - ExtBuilder::default().build().execute_with(|| { - //submit a request for representative role - RoleModule::set_role(Origin::signed(CHARLIE), CHARLIE, Acc::REPRESENTATIVE).ok(); - //approve request - //assert_ok!(AssetManagement::) - }); +fn representative() { + ExtBuilder::default().build().execute_with(|| { + //submit a request for representative role + RoleModule::set_role(Origin::signed(CHARLIE), CHARLIE, Acc::REPRESENTATIVE).ok(); + //approve request + //assert_ok!(AssetManagement::) + }); } pub fn prep_test( @@ -79,11 +78,11 @@ fn share_distributor0() { let metadata2 = b"metadata2".to_vec().try_into().unwrap(); //put some funds in FairSquare SlashFees account let fees_account = OnboardingModule::account_id(); - ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); + ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); let price1 = 40_000; let price2 = 30_000; - prep_test(price1, price2, metadata0, metadata1, metadata2); + prep_test(price1, price2, metadata0, metadata1, metadata2); let coll_id0 = NftColl::OFFICESTEST.value(); let item_id0 = pallet_nft::ItemsCount::::get()[coll_id0 as usize] - 1; let origin: OriginFor = frame_system::RawOrigin::Root.into(); @@ -99,32 +98,32 @@ fn share_distributor0() { .ok(); //Store initial owner - let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); + let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); //Execute virtual account transactions assert_ok!(ShareDistributor::virtual_account(coll_id0, item_id0)); //Store new owner - let new_owner0 = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().virtual_account; + let new_owner0 = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().virtual_account; //Execute nft transaction - assert_ok!(ShareDistributor::nft_transaction(coll_id0, item_id0, new_owner0.clone())); + assert_ok!(ShareDistributor::nft_transaction(coll_id0, item_id0, new_owner0.clone())); //Compare new & old owner - assert_ne!(old_owner0, new_owner0); + assert_ne!(old_owner0, new_owner0); //Create a FundOperation struct for this asset - let fund_op = HFund::FundOperation { + let fund_op = HFund::FundOperation { nft_collection_id: coll_id0, nft_item_id: item_id0, amount: price1, block_number: 1, contributions: vec![(EVE, 25_000), (DAVE, 15_000)], }; - let id = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().token_id; + let id = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().token_id; //Add new owners and asset to housing fund - HFund::Reservations::::insert((coll_id0, item_id0), fund_op); - println!("Reservations {:?}", HFund::Reservations::::get((coll_id0, item_id0))); - println!("Virtual Account {:?}", ShareDistributor::virtual_acc(coll_id0, item_id0)); + HFund::Reservations::::insert((coll_id0, item_id0), fund_op); + println!("Reservations {:?}", HFund::Reservations::::get((coll_id0, item_id0))); + println!("Virtual Account {:?}", ShareDistributor::virtual_acc(coll_id0, item_id0)); //Create token assert_ok!(ShareDistributor::create_tokens(origin, coll_id0, item_id0, new_owner0.clone())); @@ -147,7 +146,7 @@ fn share_distributor0() { let item_id1 = pallet_nft::ItemsCount::::get()[coll_id1 as usize] - 1; //Store initial owner - let old_owner1 = pallet_nft::Pallet::::owner(coll_id1, item_id1).unwrap(); + let old_owner1 = pallet_nft::Pallet::::owner(coll_id1, item_id1).unwrap(); //Change first asset status to FINALISED OnboardingModule::change_status( @@ -162,17 +161,17 @@ fn share_distributor0() { assert_ok!(ShareDistributor::virtual_account(coll_id1, item_id1)); //Store new owner - let new_owner1 = ShareDistributor::virtual_acc(coll_id1, item_id1).unwrap().virtual_account; + let new_owner1 = ShareDistributor::virtual_acc(coll_id1, item_id1).unwrap().virtual_account; //Execute nft transaction - assert_ok!(ShareDistributor::nft_transaction(coll_id1, item_id1, new_owner1.clone())); + assert_ok!(ShareDistributor::nft_transaction(coll_id1, item_id1, new_owner1.clone())); //Compare new & old owner - assert_ne!(old_owner1, new_owner1); + assert_ne!(old_owner1, new_owner1); //Get the virtual accounts - let virtual0 = Share::Virtual::::get(coll_id0, item_id0).unwrap(); - let virtual1 = Share::Virtual::::get(coll_id1, item_id1).unwrap(); + let virtual0 = Share::Virtual::::get(coll_id0, item_id0).unwrap(); + let virtual1 = Share::Virtual::::get(coll_id1, item_id1).unwrap(); //Check that virtual accounts are different println!("Virtual account nbr1:{:?}\nVirtual account nbr2:{:?}", virtual0, virtual1); @@ -181,14 +180,14 @@ fn share_distributor0() { assert_eq!(new_owner0, virtual0.virtual_account); assert_eq!(new_owner1, virtual1.virtual_account); - let origin3 = Origin::signed(virtual1.virtual_account); - //Representative Role status before Approval - assert_eq!(RoleModule::get_pending_representatives(FERDIE).unwrap().activated,false); + let origin3 = Origin::signed(virtual1.virtual_account); + //Representative Role status before Approval + assert_eq!(RoleModule::get_pending_representatives(FERDIE).unwrap().activated, false); - //approve FERDIE REPRESENTATIVE - assert_ok!(AssetManagement::representative_approval(origin3,FERDIE,coll_id1,item_id1)); + //approve FERDIE REPRESENTATIVE + assert_ok!(AssetManagement::representative_approval(origin3, FERDIE, coll_id1, item_id1)); //check that Ferdie is now in RepresentiveLog, and not anymore in RepApprovalList - assert_eq!(Roles::RepresentativeLog::::contains_key(FERDIE),true); - assert_eq!(Roles::RepApprovalList::::contains_key(FERDIE),false); + assert_eq!(Roles::RepresentativeLog::::contains_key(FERDIE), true); + assert_eq!(Roles::RepApprovalList::::contains_key(FERDIE), false); }); } diff --git a/pallets/bidding/src/lib.rs b/pallets/bidding/src/lib.rs index 0ff56e0f..fb116f90 100644 --- a/pallets/bidding/src/lib.rs +++ b/pallets/bidding/src/lib.rs @@ -14,9 +14,12 @@ //! * 'force_process_onboarded_asset' - extrinsic to manually launch the process of finalised assets //! //! #### Functions -//! * 'process_finalised_finalised_assets' - execute the token distribution between investors for the finalised assets -//! * 'process_onboarded_assetss' - execute the token distribution between investors for the finalised assets -//! * 'process_onboarded_assets' - execute the workflow to associate an onboarded onboarded asset to a list of investors and make and make +//! * 'process_finalised_finalised_assets' - execute the token distribution between investors for +//! the finalised assets +//! * 'process_onboarded_assetss' - execute the token distribution between investors for the +//! finalised assets +//! * 'process_onboarded_assets' - execute the workflow to associate an onboarded onboarded asset to +//! a list of investors and make and make #![cfg_attr(not(feature = "std"), no_std)] @@ -45,8 +48,7 @@ pub use pallet_share_distributor as ShareDistributor; pub mod pallet { use super::*; - use frame_system::pallet_prelude::*; - use frame_system::WeightInfo; + use frame_system::{pallet_prelude::*, WeightInfo}; pub const PERCENT_FACTOR: u64 = 100; @@ -149,8 +151,8 @@ pub mod pallet { } } -use frame_support::pallet_prelude::*; use enum_iterator::all; +use frame_support::pallet_prelude::*; impl Pallet { fn begin_block(now: T::BlockNumber) -> Weight { @@ -173,7 +175,7 @@ impl Pallet { // If no houses are found, an event is raised let block = >::block_number(); Self::deposit_event(Event::NoHousesFinalisedFound(block)); - return Ok(().into()); + return Ok(().into()) } let houses_iter = houses.iter(); @@ -215,18 +217,18 @@ impl Pallet { if houses.is_empty() { Self::deposit_event(Event::NoHousesOnboardedFound(block_number)); - return Ok(().into()); + return Ok(().into()) } for (collection_id, item_id, house) in houses.into_iter() { // Checks on price format if house.price.is_none() { - continue; + continue } let amount_wrap = Self::convert_balance(house.price.unwrap()); if amount_wrap.is_none() { - continue; + continue } let amount = amount_wrap.unwrap(); @@ -234,8 +236,13 @@ impl Pallet { // Check if Housing Fund has enough fund for the asset if !Housing_Fund::Pallet::::check_available_fund(amount) { - Self::deposit_event(Event::HousingFundNotEnough(collection_id, item_id, amount, block_number)); - continue; + Self::deposit_event(Event::HousingFundNotEnough( + collection_id, + item_id, + amount, + block_number, + )); + continue } // Retrives the ivestors list and their contributions @@ -244,9 +251,12 @@ impl Pallet { // Checki that the investor list creation was successful if investor_shares.is_empty() { Self::deposit_event(Event::FailedToAssembleInvestors( - collection_id, item_id, amount, block_number, + collection_id, + item_id, + amount, + block_number, )); - continue; + continue } Self::deposit_event(Event::InvestorListCreationSuccessful( @@ -278,18 +288,20 @@ impl Pallet { let value: T::NftCollectionId = item.value().into(); if value == collection_id { possible_collection = *item; - break; + break } } - let owner: T::AccountId = Nft::Pallet::::owner(collection_id, item_id).unwrap(); + let owner: T::AccountId = + Nft::Pallet::::owner(collection_id, item_id).unwrap(); Onboarding::Pallet::::change_status( - frame_system::RawOrigin::Signed(owner).into(), - possible_collection, - item_id, - Onboarding::AssetStatus::FINALISING - ).ok(); + frame_system::RawOrigin::Signed(owner).into(), + possible_collection, + item_id, + Onboarding::AssetStatus::FINALISING, + ) + .ok(); }, Err(_e) => { Self::deposit_event(Event::HouseBiddingFailed( @@ -299,7 +311,7 @@ impl Pallet { block_number, investor_shares, )); - continue; + continue }, } @@ -329,17 +341,17 @@ impl Pallet { // We check that the total amount of the contributions allow to buy the asset // And that the minimum number of investors is ok - if contributions.0 < amount - || contributions_length - < (percent - / Self::u64_to_balance_option(T::MaximumSharePerInvestor::get()).unwrap()) + if contributions.0 < amount || + contributions_length < + (percent / + Self::u64_to_balance_option(T::MaximumSharePerInvestor::get()).unwrap()) { - return result; + return result } // We have at least more than the maximum possible investors - if contributions_length - >= (percent / Self::u64_to_balance_option(T::MinimumSharePerInvestor::get()).unwrap()) + if contributions_length >= + (percent / Self::u64_to_balance_option(T::MinimumSharePerInvestor::get()).unwrap()) { result = Self::get_common_investor_distribution( amount, @@ -348,8 +360,8 @@ impl Pallet { ); } // We have the minimum of investors - else if contributions_length - == (percent / Self::u64_to_balance_option(T::MaximumSharePerInvestor::get()).unwrap()) + else if contributions_length == + (percent / Self::u64_to_balance_option(T::MaximumSharePerInvestor::get()).unwrap()) { result = Self::get_common_investor_distribution( amount, @@ -417,23 +429,23 @@ impl Pallet { } else if item.1 >= actual_percentage { // The current account is given a median share as its maximum available share will // break the distribution rule - item_share = actual_percentage - / Self::u64_to_balance_option(contributions_length - count + 1).unwrap(); + item_share = actual_percentage / + Self::u64_to_balance_option(contributions_length - count + 1).unwrap(); } else { // We calculate what is the share if a median rule is applied on the actual // contribution and the remaining ones - let share_median_diff = (actual_percentage - item.1) - / Self::u64_to_balance_option(contributions_length - count).unwrap(); + let share_median_diff = (actual_percentage - item.1) / + Self::u64_to_balance_option(contributions_length - count).unwrap(); // We check that the distribution between accounts will respect rules if the maximum // available share is given to the current account - if share_median_diff - < Self::u64_to_balance_option(T::MinimumSharePerInvestor::get()).unwrap() + if share_median_diff < + Self::u64_to_balance_option(T::MinimumSharePerInvestor::get()).unwrap() { // The current account is given a median share as its maximum available share // will break the distribution rule - item_share = actual_percentage - / Self::u64_to_balance_option(contributions_length - count + 1).unwrap(); + item_share = actual_percentage / + Self::u64_to_balance_option(contributions_length - count + 1).unwrap(); } else { // The account is given its maximum available share as the remaining // contributions will follow the min-max rule @@ -448,7 +460,7 @@ impl Pallet { count += 1; if actual_percentage == zero_percent { - break; + break } } @@ -539,16 +551,16 @@ impl Pallet { let mut value: Housing_Fund::BalanceOf = Self::u64_to_balance_option(0).unwrap(); // If the available amount is greater than the maximum amount, then the maximum amount is // returned - if contribution.available_balance - >= Self::get_amount_percentage(amount, T::MaximumSharePerInvestor::get()) + if contribution.available_balance >= + Self::get_amount_percentage(amount, T::MaximumSharePerInvestor::get()) { share = Self::u64_to_balance_option(T::MaximumSharePerInvestor::get()).unwrap(); value = Self::get_amount_percentage(amount, T::MaximumSharePerInvestor::get()); } // If the avalable amount is greater than the minimum but less than the maximum amount then // the share is calculated as a percentage - else if contribution.available_balance - >= Self::get_amount_percentage(amount, T::MinimumSharePerInvestor::get()) + else if contribution.available_balance >= + Self::get_amount_percentage(amount, T::MinimumSharePerInvestor::get()) { share = contribution.available_balance * Self::u64_to_balance_option(100).unwrap() / amount; @@ -562,8 +574,8 @@ impl Pallet { amount: Housing_Fund::BalanceOf, percentage: u64, ) -> Housing_Fund::BalanceOf { - amount * Self::u64_to_balance_option(percentage).unwrap() - / Self::u64_to_balance_option(100).unwrap() + amount * Self::u64_to_balance_option(percentage).unwrap() / + Self::u64_to_balance_option(100).unwrap() } fn convert_balance(amount: Onboarding::BalanceOf) -> Option> { diff --git a/pallets/bidding/src/tests.rs b/pallets/bidding/src/tests.rs index 547a18bb..7a226c4e 100644 --- a/pallets/bidding/src/tests.rs +++ b/pallets/bidding/src/tests.rs @@ -702,10 +702,7 @@ fn process_onboarded_assets_should_succeed() { events.pop(); - let event = events - .pop() - .expect("Expected at least one EventRecord to be found") - .event; + let event = events.pop().expect("Expected at least one EventRecord to be found").event; // check that the event has been raised assert_eq!( @@ -718,10 +715,9 @@ fn process_onboarded_assets_should_succeed() { )) ); - assert_eq!( - pallet_onboarding::Houses::::get(collection_id, item_id).unwrap().status, - crate::Onboarding::AssetStatus::FINALISING - ); + let asset = pallet_onboarding::Houses::::get(collection_id, item_id).unwrap(); + + assert_eq!(asset.status, crate::Onboarding::AssetStatus::FINALISING); }); } @@ -863,10 +859,7 @@ fn process_finalised_assets_should_succeed() { events.pop(); - let mut event = events - .pop() - .expect("Expected at least one EventRecord to be found") - .event; + let mut event = events.pop().expect("Expected at least one EventRecord to be found").event; // check that the event has been raised assert_eq!( diff --git a/pallets/housing_fund/src/functions.rs b/pallets/housing_fund/src/functions.rs index 7d8dc368..65ccf0b7 100644 --- a/pallets/housing_fund/src/functions.rs +++ b/pallets/housing_fund/src/functions.rs @@ -114,7 +114,9 @@ impl Pallet { } pub fn get_contributions() -> Vec<(AccountIdOf, Contribution)> { - Contributions::::iter().map(|(account_id, contribution)| (account_id, contribution)).collect() + Contributions::::iter() + .map(|(account_id, contribution)| (account_id, contribution)) + .collect() } /// Cancel a house bidding diff --git a/pallets/onboarding/src/functions.rs b/pallets/onboarding/src/functions.rs index f2cd6dac..4f89081c 100644 --- a/pallets/onboarding/src/functions.rs +++ b/pallets/onboarding/src/functions.rs @@ -159,15 +159,17 @@ impl Pallet { T::FeesAccount::get().into_account_truncating() } - fn get_houses_by_status(status: types::AssetStatus) -> Vec<( + fn get_houses_by_status( + status: types::AssetStatus, + ) -> Vec<( ::NftCollectionId, ::NftItemId, - types::Asset + types::Asset, )> { Houses::::iter() - .filter(|(_, _, house)| house.status == status) - .map(|(collection_id, item_id, house)| (collection_id, item_id, house)) - .collect() + .filter(|(_, _, house)| house.status == status) + .map(|(collection_id, item_id, house)| (collection_id, item_id, house)) + .collect() } pub fn get_onboarded_houses() -> Vec<( diff --git a/pallets/roles/src/functions.rs b/pallets/roles/src/functions.rs index d6c41082..20c050bc 100644 --- a/pallets/roles/src/functions.rs +++ b/pallets/roles/src/functions.rs @@ -17,7 +17,7 @@ impl Pallet { AccountsRolesLog::::insert(&who, Accounts::SELLER); let now = >::block_number(); Self::deposit_event(Event::SellerCreated(now, who)); - return true; + return true } } false @@ -39,7 +39,7 @@ impl Pallet { AccountsRolesLog::::insert(&who, Accounts::SERVICER); let now = >::block_number(); Self::deposit_event(Event::ServicerCreated(now, who)); - return true; + return true } } false @@ -61,7 +61,7 @@ impl Pallet { AccountsRolesLog::::insert(&who, Accounts::NOTARY); let now = >::block_number(); Self::deposit_event(Event::NotaryCreated(now, who)); - return true; + return true } } false @@ -69,9 +69,9 @@ impl Pallet { //Helper function for account creation approval by admin only pub fn approve_account(sender: T::AccountId, who: T::AccountId) -> DispatchResult { - let exist = Self::approve_seller(sender.clone(), who.clone()) - || Self::approve_servicer(sender.clone(), who.clone()) - || Self::approve_notary(sender, who); + let exist = Self::approve_seller(sender.clone(), who.clone()) || + Self::approve_servicer(sender.clone(), who.clone()) || + Self::approve_notary(sender, who); ensure!(exist, Error::::NotInWaitingList); Ok(()) } @@ -99,7 +99,7 @@ impl Pallet { }); let now = >::block_number(); Self::deposit_event(Event::SellerAccountCreationRejected(now, who.clone())); - break; + break } } @@ -111,7 +111,7 @@ impl Pallet { }); let now = >::block_number(); Self::deposit_event(Event::ServicerAccountCreationRejected(now, who)); - break; + break } } ensure!(exist, Error::::NotInWaitingList); @@ -133,9 +133,24 @@ impl Pallet { ensure!(&account != id, Error::::AlreadyWaiting); } } - ensure!(!RepApprovalList::::contains_key(&account),Error::::AlreadyWaiting); - + ensure!(!RepApprovalList::::contains_key(&account), Error::::AlreadyWaiting); Ok(()) } + + pub fn init_representatives(representatives: Vec>) { + let now = >::block_number(); + for account in representatives.into_iter() { + AccountsRolesLog::::insert(&account, Accounts::REPRESENTATIVE); + RepresentativeLog::::insert( + &account, + Representative:: { + account_id: account.clone(), + age: now, + activated: true, + assets_accounts: vec![], + }, + ); + } + } } diff --git a/pallets/roles/src/lib.rs b/pallets/roles/src/lib.rs index 93a41e59..ab627553 100644 --- a/pallets/roles/src/lib.rs +++ b/pallets/roles/src/lib.rs @@ -183,11 +183,12 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { pub new_admin: Option, + pub representatives: Vec, } #[cfg(feature = "std")] impl Default for GenesisConfig { fn default() -> Self { - Self { new_admin: Default::default() } + Self { new_admin: Default::default(), representatives: vec![] } } } @@ -198,6 +199,8 @@ pub mod pallet { let origin = T::Origin::from(RawOrigin::Signed(servicer0.clone())); //Origin let source = T::Lookup::unlookup(servicer0); //Source crate::Pallet::::set_manager(origin, source).ok(); + + crate::Pallet::::init_representatives(self.representatives.clone()); } } diff --git a/pallets/roles/src/types.rs b/pallets/roles/src/types.rs index 1a76a279..fa809a11 100644 --- a/pallets/roles/src/types.rs +++ b/pallets/roles/src/types.rs @@ -195,9 +195,9 @@ where assets_accounts: Vec::new(), }; - RepApprovalList::::mutate(caller,|val| { + RepApprovalList::::mutate(caller, |val| { //val.push(rep); - *val=Some(rep); + *val = Some(rep); }); Ok(()) diff --git a/pallets/share_distributor/src/tests.rs b/pallets/share_distributor/src/tests.rs index b25b3b3a..92325149 100644 --- a/pallets/share_distributor/src/tests.rs +++ b/pallets/share_distributor/src/tests.rs @@ -73,11 +73,11 @@ fn share_distributor0() { let metadata2 = b"metadata2".to_vec().try_into().unwrap(); //put some funds in FairSquare SlashFees account let fees_account = Onboarding::Pallet::::account_id(); - ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); + ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); let price1 = 40_000; let price2 = 30_000; - prep_test(price1, price2, metadata0, metadata1, metadata2); + prep_test(price1, price2, metadata0, metadata1, metadata2); let coll_id0 = NftColl::OFFICESTEST.value(); let item_id0 = pallet_nft::ItemsCount::::get()[coll_id0 as usize] - 1; let origin: OriginFor = frame_system::RawOrigin::Root.into(); @@ -93,32 +93,32 @@ fn share_distributor0() { .ok(); //Store initial owner - let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); + let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); //Execute virtual account transactions assert_ok!(ShareDistributor::virtual_account(coll_id0, item_id0)); //Store new owner - let new_owner0 = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().virtual_account; + let new_owner0 = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().virtual_account; //Execute nft transaction - assert_ok!(ShareDistributor::nft_transaction(coll_id0, item_id0, new_owner0.clone())); + assert_ok!(ShareDistributor::nft_transaction(coll_id0, item_id0, new_owner0.clone())); //Compare new & old owner - assert_ne!(old_owner0, new_owner0); + assert_ne!(old_owner0, new_owner0); //Create a FundOperation struct for this asset - let fund_op = HousingFund::FundOperation { + let fund_op = HousingFund::FundOperation { nft_collection_id: coll_id0, nft_item_id: item_id0, amount: price1, block_number: 1, contributions: vec![(EVE, 25_000), (DAVE, 15_000)], }; - let id = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().token_id; + let id = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().token_id; //Add new owners and asset to housing fund - HousingFund::Reservations::::insert((coll_id0, item_id0), fund_op); - println!("Reservations {:?}", HousingFund::Reservations::::get((coll_id0, item_id0))); - println!("Virtual Account {:?}", ShareDistributor::virtual_acc(coll_id0, item_id0)); + HousingFund::Reservations::::insert((coll_id0, item_id0), fund_op); + println!("Reservations {:?}", HousingFund::Reservations::::get((coll_id0, item_id0))); + println!("Virtual Account {:?}", ShareDistributor::virtual_acc(coll_id0, item_id0)); //Create token assert_ok!(ShareDistributor::create_tokens(origin, coll_id0, item_id0, new_owner0.clone())); @@ -141,7 +141,7 @@ fn share_distributor0() { let item_id1 = pallet_nft::ItemsCount::::get()[coll_id1 as usize] - 1; //Store initial owner - let old_owner1 = pallet_nft::Pallet::::owner(coll_id1, item_id1).unwrap(); + let old_owner1 = pallet_nft::Pallet::::owner(coll_id1, item_id1).unwrap(); //Change first asset status to FINALISED Onboarding::Pallet::::change_status( @@ -156,17 +156,17 @@ fn share_distributor0() { assert_ok!(ShareDistributor::virtual_account(coll_id1, item_id1)); //Store new owner - let new_owner1 = ShareDistributor::virtual_acc(coll_id1, item_id1).unwrap().virtual_account; + let new_owner1 = ShareDistributor::virtual_acc(coll_id1, item_id1).unwrap().virtual_account; //Execute nft transaction - assert_ok!(ShareDistributor::nft_transaction(coll_id1, item_id1, new_owner1.clone())); + assert_ok!(ShareDistributor::nft_transaction(coll_id1, item_id1, new_owner1.clone())); //Compare new & old owner - assert_ne!(old_owner1, new_owner1); + assert_ne!(old_owner1, new_owner1); //Get the virtual accounts - let virtual0 = Virtual::::get(coll_id0, item_id0).unwrap(); - let virtual1 = Virtual::::get(coll_id1, item_id1).unwrap(); + let virtual0 = Virtual::::get(coll_id0, item_id0).unwrap(); + let virtual1 = Virtual::::get(coll_id1, item_id1).unwrap(); //Check that virtual accounts are different println!("Virtual account nbr1:{:?}\nVirtual account nbr2:{:?}", virtual0, virtual1); @@ -185,11 +185,11 @@ fn share_distributor1() { let metadata2 = b"metadata2".to_vec().try_into().unwrap(); //put some funds in FairSquare SlashFees account let fees_account = Onboarding::Pallet::::account_id(); - ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); + ::Currency::make_free_balance_be(&fees_account, 150_000u32.into()); let price1 = 40_000; let price2 = 30_000; - prep_test(price1, price2, metadata0, metadata1, metadata2); + prep_test(price1, price2, metadata0, metadata1, metadata2); let coll_id0 = NftColl::OFFICESTEST.value(); let item_id0 = pallet_nft::ItemsCount::::get()[coll_id0 as usize] - 1; let origin: OriginFor = frame_system::RawOrigin::Root.into(); @@ -228,7 +228,7 @@ fn share_distributor1() { HousingFund::Contributions::::insert(DAVE, contribution_dave); //Create a FundOperation struct for this asset - let fund_op = HousingFund::FundOperation { + let fund_op = HousingFund::FundOperation { nft_collection_id: coll_id0, nft_item_id: item_id0, amount: price1, @@ -237,7 +237,7 @@ fn share_distributor1() { }; //Add new owners and asset to housing fund - HousingFund::Reservations::::insert((coll_id0, item_id0), fund_op); + HousingFund::Reservations::::insert((coll_id0, item_id0), fund_op); // Update the Housing fund to fit with the contributions HousingFund::FundBalance::::mutate(|val| { @@ -254,9 +254,9 @@ fn share_distributor1() { .ok(); //Store initial owner - let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); + let old_owner0 = pallet_nft::Pallet::::owner(coll_id0, item_id0).unwrap(); - assert_ok!(ShareDistributor::create_virtual(origin, coll_id0, item_id0)); + assert_ok!(ShareDistributor::create_virtual(origin, coll_id0, item_id0)); let when = >::block_number(); let new_owner0 = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().virtual_account; let owners = ShareDistributor::virtual_acc(coll_id0, item_id0).unwrap().owners; diff --git a/pallets/voting/src/lib.rs b/pallets/voting/src/lib.rs index 513a1206..1f60c8e5 100644 --- a/pallets/voting/src/lib.rs +++ b/pallets/voting/src/lib.rs @@ -56,8 +56,7 @@ pub mod pallet { traits::{ReservableCurrency, UnfilteredDispatchable}, weights::GetDispatchInfo, }; - use frame_system::pallet_prelude::*; - use frame_system::WeightInfo; + use frame_system::{pallet_prelude::*, WeightInfo}; use scale_info::prelude::boxed::Box; diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index d9799030..cade9808 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -53,6 +53,7 @@ pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "p pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false } pallet-preimage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false } pallet-assets = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false } +pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.29", default-features = false } # Used for the node template's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" } @@ -111,6 +112,7 @@ std = [ "pallet-scheduler/std", "pallet-preimage/std", "pallet-treasury/std", + "pallet-identity/std", "pallet-roles/std", "pallet-housing_fund/std", "pallet-nft/std", @@ -134,12 +136,13 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "pallet-roles/runtime-benchmarks", "pallet-housing_fund/runtime-benchmarks", "pallet-nft/runtime-benchmarks", "pallet-voting/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", "pallet-onboarding/runtime-benchmarks", "pallet-share_distributor/runtime-benchmarks", "pallet-bidding/runtime-benchmarks", @@ -159,11 +162,12 @@ try-runtime = [ "pallet-sudo/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-identity/try-runtime", "pallet-roles/try-runtime", "pallet-housing_fund/try-runtime", "pallet-nft/try-runtime", "pallet-voting/try-runtime", - "pallet-utility/try-runtime", "pallet-onboarding/try-runtime", "pallet-share_distributor/try-runtime", "pallet-bidding/try-runtime", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 632b2eee..2acedf01 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -43,24 +43,24 @@ use frame_system::{ EnsureRoot, EnsureSigned, }; pub use pallet_balances::Call as BalancesCall; +pub use pallet_democracy; +use pallet_nft::NftPermissions; +pub use pallet_nft::{self, Acc, CollectionId, ItemId, NftPermission}; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::CurrencyAdapter; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; -pub use pallet_democracy; -use pallet_nft::NftPermissions; -pub use pallet_nft::{self, Acc, CollectionId, ItemId, NftPermission}; +pub use pallet_asset_management; +pub use pallet_bidding; +pub use pallet_housing_fund; +pub use pallet_onboarding; /// Import the template pallet. pub use pallet_roles; -pub use pallet_housing_fund; +pub use pallet_share_distributor; pub use pallet_utility; pub use pallet_voting; -pub use pallet_onboarding; -pub use pallet_share_distributor; -pub use pallet_bidding; -pub use pallet_asset_management; pub use pallet_finalizer; // flag add pallet use @@ -126,8 +126,6 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { state_version: 1, }; - - /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { @@ -142,7 +140,6 @@ const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// We allow for 2 seconds of compute with a 6 second average block time. const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.saturating_mul(2); - parameter_types! { pub const BlockHashCount: BlockNumber = 2400; pub const Version: RuntimeVersion = VERSION; @@ -329,6 +326,30 @@ impl pallet_uniques::Config for Runtime { type Locker = (); } +parameter_types! { + pub const BasicDeposit: Balance = 10 * DOLLARS; // 258 bytes on-chain + pub const FieldDeposit: Balance = 250 * CENTS; // 66 bytes on-chain + pub const SubAccountDeposit: Balance = 2 * DOLLARS; // 53 bytes on-chain + pub const MaxAdditionalFields: u32 = 100; + pub const MaxRegistrars: u32 = 1; + pub const MaxSubAccounts: u32 = 100; +} + +impl pallet_identity::Config for Runtime { + type Event = Event; + type Currency = Balances; + type BasicDeposit = BasicDeposit; + type FieldDeposit = FieldDeposit; + type MaxRegistrars = MaxRegistrars; + type ForceOrigin = EnsureRoot; + type RegistrarOrigin = EnsureRoot; + type MaxAdditionalFields = MaxAdditionalFields; + type MaxSubAccounts = MaxSubAccounts; + type Slashed = Treasury; + type SubAccountDeposit = SubAccountDeposit; + type WeightInfo = pallet_identity::weights::SubstrateWeight; +} + parameter_types! { pub const MaxMembers:u32 =200; } @@ -336,7 +357,7 @@ parameter_types! { impl pallet_roles::Config for Runtime { type Event = Event; type Currency = Balances; - type WeightInfo = pallet_roles::weights::SubstrateWeight; + type WeightInfo = pallet_roles::weights::SubstrateWeight; type MaxMembers = MaxMembers; } @@ -656,6 +677,7 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment, Uniques: pallet_uniques, Sudo: pallet_sudo, + Identity: pallet_identity, RoleModule: pallet_roles, HousingFundModule: pallet_housing_fund, NftModule: pallet_nft, @@ -721,6 +743,7 @@ mod benches { [pallet_nft, NftModule] [pallet_onboarding, OnboardingModule] [pallet_share_distributor,ShareDistributor] + [pallet_identity, Identity] //[pallet_asset_management, AssetManagementModule] // [pallet_finalizer, FinalizerModule] // flag add pallet bench_macro