diff --git a/Cargo.lock b/Cargo.lock index 33a9c2a4..4d55637f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2483,7 +2483,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-runtime-interface", - "sp-std", + "sp-std 8.0.0", "sp-storage", "static_assertions", ] @@ -2550,7 +2550,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-tracing", ] @@ -2610,7 +2610,7 @@ dependencies = [ "serde_json", "smallvec", "sp-api", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-core", "sp-core-hashing-proc-macro", "sp-debug-derive", @@ -2621,7 +2621,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-state-machine", - "sp-std", + "sp-std 8.0.0", "sp-tracing", "sp-weights", "static_assertions", @@ -2682,7 +2682,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-version", "sp-weights", ] @@ -2699,7 +2699,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -2720,7 +2720,7 @@ dependencies = [ "parity-scale-codec", "sp-api", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -2804,6 +2804,7 @@ dependencies = [ "pallet-preimage", "pallet-roles", "pallet-scheduler", + "pallet-share_distributor", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -2822,7 +2823,7 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", - "sp-std", + "sp-std 8.0.0", "sp-storage", "sp-transaction-pool", "sp-version", @@ -5137,7 +5138,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5154,7 +5155,7 @@ dependencies = [ "sp-application-crypto", "sp-consensus-aura", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5168,7 +5169,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5183,7 +5184,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5209,7 +5210,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5226,7 +5227,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5248,7 +5249,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5266,7 +5267,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5290,7 +5291,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5313,7 +5314,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5335,7 +5336,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5351,7 +5352,7 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5373,7 +5374,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5391,7 +5392,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5427,7 +5428,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5444,7 +5445,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5463,7 +5464,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5480,7 +5481,7 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-weights", ] @@ -5502,10 +5503,36 @@ dependencies = [ "sp-session", "sp-staking", "sp-state-machine", - "sp-std", + "sp-std 8.0.0", "sp-trie", ] +[[package]] +name = "pallet-share_distributor" +version = "4.0.0-dev" +dependencies = [ + "enum-iterator", + "frame-benchmarking", + "frame-support", + "frame-system", + "num-traits", + "pallet-assets", + "pallet-balances", + "pallet-housing_fund", + "pallet-nft", + "pallet-onboarding", + "pallet-roles", + "pallet-sudo", + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic 19.0.0", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" @@ -5518,7 +5545,7 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5549,7 +5576,7 @@ dependencies = [ "sp-inherents", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-storage", "sp-timestamp", ] @@ -5567,7 +5594,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5612,7 +5639,7 @@ dependencies = [ "scale-info", "serde", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5627,7 +5654,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -5643,7 +5670,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -7018,7 +7045,7 @@ dependencies = [ "sc-client-api", "sc-state-db", "schnellru", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-blockchain", "sp-core", "sp-database", @@ -7111,7 +7138,7 @@ dependencies = [ "serde_json", "sp-api", "sp-application-crypto", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", @@ -7135,7 +7162,7 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-slots", @@ -7256,7 +7283,7 @@ dependencies = [ "serde", "serde_json", "smallvec", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-blockchain", "sp-core", "sp-runtime", @@ -7367,7 +7394,7 @@ dependencies = [ "sc-utils", "schnellru", "smallvec", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", @@ -7641,7 +7668,7 @@ dependencies = [ "serde_json", "sp-core", "sp-io", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -7757,7 +7784,7 @@ dependencies = [ "log", "parking_lot 0.12.1", "prometheus", - "sp-arithmetic", + "sp-arithmetic 16.0.0", ] [[package]] @@ -8089,10 +8116,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "share_distributor" -version = "0.1.0" - [[package]] name = "shlex" version = "1.1.0" @@ -8243,7 +8266,7 @@ dependencies = [ "sp-metadata-ir", "sp-runtime", "sp-state-machine", - "sp-std", + "sp-std 8.0.0", "sp-trie", "sp-version", "thiserror", @@ -8273,7 +8296,7 @@ dependencies = [ "serde", "sp-core", "sp-io", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8286,7 +8309,21 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", + "sp-std 8.0.0", + "static_assertions", +] + +[[package]] +name = "sp-arithmetic" +version = "19.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e41f710a77e9debd1c9b80f862709dce648e50f0904cde4117488e7d11d4796d" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "sp-std 11.0.0", "static_assertions", ] @@ -8298,7 +8335,7 @@ dependencies = [ "sp-api", "sp-inherents", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8347,7 +8384,7 @@ dependencies = [ "sp-consensus-slots", "sp-inherents", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-timestamp", ] @@ -8366,7 +8403,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-timestamp", ] @@ -8385,7 +8422,7 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8396,7 +8433,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std", + "sp-std 8.0.0", "sp-timestamp", ] @@ -8437,7 +8474,7 @@ dependencies = [ "sp-debug-derive", "sp-externalities", "sp-runtime-interface", - "sp-std", + "sp-std 8.0.0", "sp-storage", "ss58-registry", "substrate-bip39", @@ -8496,7 +8533,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.1.0#f60 dependencies = [ "environmental", "parity-scale-codec", - "sp-std", + "sp-std 8.0.0", "sp-storage", ] @@ -8508,7 +8545,7 @@ dependencies = [ "serde_json", "sp-api", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8521,7 +8558,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "thiserror", ] @@ -8542,7 +8579,7 @@ dependencies = [ "sp-keystore", "sp-runtime-interface", "sp-state-machine", - "sp-std", + "sp-std 8.0.0", "sp-tracing", "sp-trie", "tracing", @@ -8589,7 +8626,7 @@ dependencies = [ "frame-metadata", "parity-scale-codec", "scale-info", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8637,10 +8674,10 @@ dependencies = [ "scale-info", "serde", "sp-application-crypto", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-core", "sp-io", - "sp-std", + "sp-std 8.0.0", "sp-weights", ] @@ -8655,7 +8692,7 @@ dependencies = [ "primitive-types", "sp-externalities", "sp-runtime-interface-proc-macro", - "sp-std", + "sp-std 8.0.0", "sp-storage", "sp-tracing", "sp-wasm-interface", @@ -8686,7 +8723,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-staking", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8700,7 +8737,7 @@ dependencies = [ "serde", "sp-core", "sp-runtime", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8717,7 +8754,7 @@ dependencies = [ "sp-core", "sp-externalities", "sp-panic-handler", - "sp-std", + "sp-std 8.0.0", "sp-trie", "thiserror", "tracing", @@ -8743,7 +8780,7 @@ dependencies = [ "sp-externalities", "sp-runtime", "sp-runtime-interface", - "sp-std", + "sp-std 8.0.0", "thiserror", "x25519-dalek 2.0.0", ] @@ -8753,6 +8790,12 @@ name = "sp-std" version = "8.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.1.0#f60318f68687e601c47de5ad5ca88e2c3f8139a7" +[[package]] +name = "sp-std" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c91d32e165d08a14098ce5ec923eaec59d1d0583758a18a770beec1b780b0d0" + [[package]] name = "sp-storage" version = "13.0.0" @@ -8763,7 +8806,7 @@ dependencies = [ "ref-cast", "serde", "sp-debug-derive", - "sp-std", + "sp-std 8.0.0", ] [[package]] @@ -8775,7 +8818,7 @@ dependencies = [ "parity-scale-codec", "sp-inherents", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "thiserror", ] @@ -8785,7 +8828,7 @@ version = "10.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.1.0#f60318f68687e601c47de5ad5ca88e2c3f8139a7" dependencies = [ "parity-scale-codec", - "sp-std", + "sp-std 8.0.0", "tracing", "tracing-core", "tracing-subscriber", @@ -8811,7 +8854,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-trie", ] @@ -8831,7 +8874,7 @@ dependencies = [ "scale-info", "schnellru", "sp-core", - "sp-std", + "sp-std 8.0.0", "thiserror", "tracing", "trie-db", @@ -8850,7 +8893,7 @@ dependencies = [ "serde", "sp-core-hashing-proc-macro", "sp-runtime", - "sp-std", + "sp-std 8.0.0", "sp-version-proc-macro", "thiserror", ] @@ -8875,7 +8918,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std", + "sp-std 8.0.0", "wasmtime", ] @@ -8888,10 +8931,10 @@ dependencies = [ "scale-info", "serde", "smallvec", - "sp-arithmetic", + "sp-arithmetic 16.0.0", "sp-core", "sp-debug-derive", - "sp-std", + "sp-std 8.0.0", ] [[package]] diff --git a/pallets/share_distributor/Cargo.toml b/pallets/share_distributor/Cargo.toml index 4d4eff0b..ea0263bb 100644 --- a/pallets/share_distributor/Cargo.toml +++ b/pallets/share_distributor/Cargo.toml @@ -1,8 +1,68 @@ [package] -name = "share_distributor" -version = "0.1.0" +name = "pallet-share_distributor" +version = "4.0.0-dev" +description = "Distribute to the asset new owners/contributors, the ownership nft, and the ownership token" +authors = ["Fair Squares"] +homepage = "https://fair-squares.nl" edition = "2021" +license = "Apache 2.0" +publish = false +repository = "https://github.com/Fair-Squares/fair-squares" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +enum-iterator = "1.4.1" +num-traits = {version="0.2.17",default-features = false} +sp-arithmetic = {version="19.0.0",default-features = false} +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +sp-std = { default-features = false, version = "8.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +pallet-assets = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +serde = { version = "1.0.183", default-features = false, features = ["derive"] } +pallet-roles = { default-features = false, path="../roles" } +pallet-onboarding = { default-features = false, path="../onboarding" } +pallet-housing_fund = { default-features = false, path="../housing_fund" } +pallet-nft = { default-features = false, path="../nft" } + +[dev-dependencies] +sp-core = { version = "21.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +sp-io = { version = "23.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } +sp-runtime = { version = "24.0.0", git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "serde/std", + "sp-std/std", + "pallet-balances/std", + "pallet-sudo/std", + "pallet-roles/std", + "pallet-onboarding/std", + "pallet-nft/std", + "pallet-housing_fund/std", + "pallet-assets/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + ] + +try-runtime = [ + "frame-support/try-runtime", + ] diff --git a/pallets/share_distributor/src/functions.rs b/pallets/share_distributor/src/functions.rs new file mode 100644 index 00000000..963afb73 --- /dev/null +++ b/pallets/share_distributor/src/functions.rs @@ -0,0 +1,230 @@ +use super::*; +use enum_iterator::all; +#[allow(unused_imports)] +use num_traits::float::FloatCore; +use sp_runtime::{traits::SaturatedConversion, FixedPointNumber, FixedU128}; + +impl Pallet { + + pub fn virtual_account( + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + ) -> DispatchResult { + //Create virtual account + let text0 = format!("{collection_id:?}_{:?}_account", item_id.clone()); + let bytes = text0.as_bytes(); + let array: &[u8; 8] = &bytes[0..8].try_into().unwrap(); + let account: T::AccountId = PalletId(*array).into_account_truncating(); + + //Store account inside storage + Ownership::::new(collection_id, item_id, account.clone()).ok(); + Owners::::new(account.clone()).ok(); + + //The virtual account needs some initial funds to pay for asset creation fees + //These funds could be provided by the FairSquare FeesAccount maintained in the + //Onboarding pallet. + let fees_account = Onboarding::Pallet::::account_id(); + let fees = T::Fees::get(); + //Ensure that we have enough money in the fees_account + let balance = ::Currency::free_balance(&fees_account); + ensure!(fees < balance, Error::::NotEnoughFees); + + let res = ::Currency::transfer( + &fees_account, + &account, + fees, + ExistenceRequirement::AllowDeath, + ); + debug_assert!(res.is_ok()); + + Ok(()) + } + + ///This function executes all actions relatives to nft transfer from the seller to the virtual + /// account + pub fn nft_transaction( + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + virtual_id: T::AccountId, + ) -> DispatchResult { + //Get collection + let collection_vec = all::().collect::>(); + let _infos = Onboarding::Houses::::get(collection_id, item_id).unwrap(); + let mut coll_id = Nft::PossibleCollections::HOUSES; + for i in collection_vec.iter() { + let val: T::NftCollectionId = i.value().into(); + if val == collection_id { + coll_id = *i; + } + } + //Execute NFT and money transfer + Onboarding::Pallet::do_buy(coll_id, item_id, virtual_id, _infos).ok(); + + Ok(()) + } + + ///Collect contributors to the bid, and their shares + pub fn owner_and_shares( + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + _total_tokens: ::Balance, + ) -> Vec<(T::AccountId, u128)> { + //Get owners and their reserved contribution to the bid + + let reservation_infos = + HousingFund::Reservations::::get((collection_id, item_id)).unwrap(); + let vec0 = reservation_infos.contributions; + let price = reservation_infos.amount; + let virtual_acc = Self::virtual_acc(collection_id, item_id).unwrap().virtual_account; + + let mut vec = Vec::new(); + for i in vec0.iter() { + let price0 = Self::hfund_bal_to_u128(price).unwrap(); + let contribution0 = Self::hfund_bal_to_u128(i.1).unwrap(); + + let price1 = Self::balance_to_f64_option0(price).unwrap(); + let contribution1 = Self::balance_to_f64_option0(i.1).unwrap(); + let frac = (contribution1 / price1).round(); + let mut share = FixedU128::saturating_from_rational(contribution0, price0) + .saturating_mul_int(1000u128); + let fl = share as f64; + if (fl + 0.5) < frac { + share += 1; + } + + debug_assert!(share < 1000); + debug_assert!(share > 0); + + vec.push((i.0.clone(), share)); + //Update Virtual_account storage + let mut val0 = Self::virtual_acc(collection_id,item_id).unwrap(); + let _=val0.owners.try_push(i.0.clone()); + Virtual::::mutate(collection_id, item_id, |val| { + + *val = Some(val0); + }); + let amount: ::Balance = + share.saturated_into::<::Balance>(); + let mut val0 = Self::tokens_infos(virtual_acc.clone()).unwrap(); + //Update owners in Tokens storage + Tokens::::mutate(&virtual_acc, |val| { + + let _=val0.owners.try_push((i.0.clone(), amount)); + *val = Some(val0); + }); + } + vec + } + + ///Create 1000 Ownership tokens owned by a virtual account + pub fn create_tokens( + origin: OriginFor, + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + account: T::AccountId, + ) -> DispatchResult { + //Get token class Id: + ensure!(Virtual::::get(collection_id, item_id).is_some(), Error::::InvalidValue); + let token_id = Virtual::::get(collection_id, item_id).unwrap().token_id; + let to = T::Lookup::unlookup(account.clone()); + TokenId::::mutate(|val| { + let val0 = *val; + *val = val0 + 1; + }); + + //Create token class + let res = Assets::Pallet::::force_create( + origin.clone(), + token_id.into(), + to.clone(), + true, + One::one(), + ); + debug_assert!(res.is_ok()); + + //Set class metadata + let token_name = format!("FairOwner_nbr{:?}", token_id.clone()).as_bytes().to_vec(); + let token_symbol = format!("FO{:?}", token_id.clone()).as_bytes().to_vec(); + let decimals = 1; + Assets::Pallet::::force_set_metadata( + origin, + token_id.into(), + token_name, + token_symbol, + decimals, + false, + ) + .ok(); + + //mint 1000 tokens + let res0 = Assets::Pallet::::mint( + RawOrigin::Signed(account.clone()).into(), + token_id.into(), + to, + Self::u32_to_balance_option(1000).unwrap(), + ); + debug_assert!(res0.is_ok()); + let mut val0 = Self::tokens_infos(account.clone()).unwrap(); + //Update supply in Tokens storage + Tokens::::mutate(account, |val| { + + val0.supply = Assets::Pallet::::total_supply(token_id.into()); + *val = Some(val0); + }); + + Ok(()) + } + + ///Distribute the ownership tokens to the group of new owners + pub fn distribute_tokens( + account: T::AccountId, + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + ) -> DispatchResult { + ensure!(Virtual::::get(collection_id, item_id).is_some(), Error::::InvalidValue); + let token_id = Virtual::::get(collection_id, item_id).unwrap().token_id; + let total_tokens = Assets::Pallet::::total_supply(token_id.into()); + debug_assert!(total_tokens == Self::u32_to_balance_option(1000).unwrap()); + let shares = Self::owner_and_shares(collection_id, item_id, total_tokens); + + let from = T::Lookup::unlookup(account.clone()); + let origin: OriginFor = RawOrigin::Signed(account).into(); + + for share in shares.iter() { + let amount0 = share.clone().1; + debug_assert!(amount0 > 0); + let amount: ::Balance = + share.clone().1.saturated_into::<::Balance>(); + debug_assert!(!amount.clone().is_zero()); + let to = T::Lookup::unlookup(share.clone().0); + Assets::Pallet::::force_transfer( + origin.clone(), + token_id.into(), + from.clone(), + to, + amount, + ) + .ok(); + } + + Ok(()) + } + + // Conversion of u32 to Balance + pub fn u32_to_balance_option(input: u32) -> Option { + input.try_into().ok() + } + + // Conversion of BalanceOf to u128 + pub fn hfund_bal_to_u128(input: HousingFund::BalanceOf) -> Option { + input.try_into().ok() + } + + // Conversion of BalanceOf to f64 + pub fn balance_to_f64_option0(input: HousingFund::BalanceOf) -> Option { + let integer: u64 = input.try_into().ok().unwrap(); + let float = integer as f64; + Some(float) + } + +} \ No newline at end of file diff --git a/pallets/share_distributor/src/lib.rs b/pallets/share_distributor/src/lib.rs new file mode 100644 index 00000000..7d9383fe --- /dev/null +++ b/pallets/share_distributor/src/lib.rs @@ -0,0 +1,215 @@ + +// We make sure this pallet uses `no_std` for compiling to Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; +pub use pallet_assets as Assets; +pub use pallet_housing_fund as HousingFund; +pub use pallet_nft as Nft; +pub use pallet_onboarding as Onboarding; +pub use pallet_roles as Roles; +mod functions; +mod types; +pub use functions::*; +pub use types::*; + +//#[cfg(test)] +//mod mock; + +//#[cfg(test)] +//mod tests; + +//#[cfg(feature = "runtime-benchmarks")] +//mod benchmarking; +//pub mod weights; +//pub use weights::*; + +// All pallet logic is defined in its own module and must be annotated by the `pallet` attribute. +#[frame_support::pallet] +pub mod pallet { + // Import various useful types required by all FRAME pallets. + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + // The `Pallet` struct serves as a placeholder to implement traits, methods and dispatchables + // (`Call`s) in this pallet. + #[pallet::pallet] + pub struct Pallet(_); + + + #[pallet::config] + pub trait Config: + frame_system::Config + + Assets::Config + + Roles::Config + + Nft::Config + + Onboarding::Config + + HousingFund::Config { + /// The overarching runtime event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type AssetId: + IsType<::AssetIdParameter> + + Into<::AssetId> + + Parameter + + From + + Ord + + Copy + +MaxEncodedLen; + #[pallet::constant] + type Fees: Get>; + #[pallet::constant] + type MaxOwners: Get; + } + + #[pallet::storage] + #[pallet::getter(fn something)] + pub type Something = StorageValue<_, u32>; + + #[pallet::storage] + #[pallet::getter(fn virtual_acc)] + /// Stores Virtual accounts + pub type Virtual = StorageDoubleMap< + _, + Blake2_128Concat, + T::NftCollectionId, + Blake2_128Concat, + T::NftItemId, + Ownership, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn tokens_infos)] + /// Stores Tokens infos + pub type Tokens = + StorageMap<_, Blake2_128Concat, T::AccountId, Owners, OptionQuery>; + + #[pallet::type_value] + ///Initializing Token id to value 0 + pub fn InitDefault() -> u32 { + 0 + } + + #[pallet::storage] + #[pallet::getter(fn token_id)] + /// Stores Ownership Tokens id number + pub type TokenId = StorageValue<_, u32, ValueQuery, InitDefault>; + + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A user has successfully set a new value. + SomethingStored { + /// The new value set. + something: u32, + /// The account who set the new value. + who: T::AccountId, + }, + /// A virtual account was created + VirtualCreated { + account: T::AccountId, + collection: T::NftCollectionId, + item: T::NftItemId, + when: BlockNumberOf, + }, + /// NFT Transaction Executed + NftTransactionExecuted { + nft_transfer_to: T::AccountId, + nft_transfer_from: T::AccountId, + when: BlockNumberOf, + }, + ///Ownership Token distributed to new owners + OwnershipTokensDistributed { + from: T::AccountId, + to: BoundedVec, + token_id: ::AssetId, + owners: BoundedVec<(T::AccountId, ::Balance),T::MaxOwners>, + }, + } + + /// Errors that can be returned by this pallet. + /// + /// Errors tell users that something went wrong so it's important that their naming is + /// informative. Similar to events, error documentation is added to a node's metadata so it's + /// equally important that they have helpful documentation associated with them. + /// + /// This type of runtime error can be up to 4 bytes in size should you want to return additional + /// information. + #[pallet::error] + pub enum Error { + /// Not a value. + NoneValue, + /// Ivalid parameter + InvalidValue, + /// This action is reserved to Accounts holding the SERVICER role. + ReservedToServicer, + /// Not enough funds in the fees_account + NotEnoughFees, + } + + #[pallet::call] + impl Pallet { + /// An example dispatchable that takes a single u32 value as a parameter, writes the value + /// to storage and emits an event. + /// + /// It checks that the _origin_ for this call is _Signed_ and returns a dispatch + /// error if it isn't. Learn more about origins here: + #[pallet::call_index(0)] + #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1).ref_time())] + pub fn create_virtual( + origin: OriginFor, + collection_id: T::NftCollectionId, + item_id: T::NftItemId, + ) -> DispatchResult { + let _caller = ensure_root(origin.clone()); + let seller: T::AccountId = Nft::Pallet::::owner(collection_id, item_id).unwrap(); + // Create virtual account + Self::virtual_account(collection_id, item_id).ok(); + let account = Self::virtual_acc(collection_id, item_id).unwrap().virtual_account; + + // execute NFT transaction + Self::nft_transaction(collection_id, item_id, account.clone()).ok(); + + //Create new token class + Self::create_tokens(origin, collection_id, item_id, account.clone()).ok(); + + //distribute tokens + Self::distribute_tokens(account.clone(), collection_id, item_id).ok(); + + // Update Housing fund informations + HousingFund::Pallet::::validate_house_bidding(collection_id, item_id).ok(); + + // Emit some events. + let created = >::block_number(); + Self::deposit_event(Event::VirtualCreated { + account: account.clone(), + collection: collection_id, + item: item_id, + when: created, + }); + + Self::deposit_event(Event::NftTransactionExecuted { + nft_transfer_to: account.clone(), + nft_transfer_from: seller, + when: created, + }); + + let new_owners = Self::virtual_acc(collection_id, item_id).unwrap().owners; + let token_id = Self::virtual_acc(collection_id, item_id).unwrap().token_id; + let owners = Self::tokens_infos(account.clone()).unwrap().owners; + Self::deposit_event(Event::OwnershipTokensDistributed { + from: account, + to: new_owners, + token_id, + owners, + }); + + Ok(()) + } + + + } +} \ No newline at end of file diff --git a/pallets/share_distributor/src/main.rs b/pallets/share_distributor/src/main.rs deleted file mode 100644 index a30eb952..00000000 --- a/pallets/share_distributor/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/pallets/share_distributor/src/types.rs b/pallets/share_distributor/src/types.rs new file mode 100644 index 00000000..6898fdaf --- /dev/null +++ b/pallets/share_distributor/src/types.rs @@ -0,0 +1,88 @@ +pub use super::*; +pub use frame_support::{ + assert_ok, + dispatch::{DispatchResult}, + pallet_prelude::*, + sp_runtime::{ + traits::{AccountIdConversion, Hash, One, Saturating, StaticLookup, Zero}, + PerThing, Percent, + }, + storage::{child,bounded_vec::BoundedVec}, + traits::{ + Currency, ExistenceRequirement, Get, LockableCurrency, ReservableCurrency, WithdrawReasons, + }, + PalletId, +}; + +pub use frame_system::{ensure_signed, pallet_prelude::*, RawOrigin}; +pub use scale_info::{ + prelude::{format, vec::Vec}, + TypeInfo +}; +pub use serde::{Deserialize, Serialize}; +pub type BlockNumberOf = BlockNumberFor; +pub type BalanceOf = +<::Currency as Currency<::AccountId>>::Balance; + +#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo,MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Owners { + pub owners: BoundedVec<(T::AccountId, ::Balance),T::MaxOwners>, + ///Creation Blocknumber + pub created_at_block: BlockNumberOf, + ///TokenId + pub token_id: ::AssetId, + ///Total supply of tokens + pub supply: ::Balance, +} + +impl Owners { + pub fn new(virtual_account: T::AccountId) -> DispatchResult { + let own = Vec::new(); + let owners = BoundedVec::truncate_from(own); + let created_at_block = >::block_number(); + let token_id: ::AssetId = TokenId::::get().into(); + let supply = Zero::zero(); + let tokens = Owners:: { owners, created_at_block, token_id, supply }; + + Tokens::::insert(virtual_account, tokens); + + Ok(()) + } +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo,MaxEncodedLen)] +#[scale_info(skip_type_params(T))] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Ownership { + /// Virtual account + pub virtual_account: T::AccountId, + /// NFT owners accounts list + pub owners: BoundedVec, + ///Creation Blocknumber + pub created: BlockNumberOf, + ///TokenId + pub token_id: ::AssetId, + ///Number of rents awaiting distribution + pub rent_nbr: u32, +} + +impl Ownership { + pub fn new( + collection: T::NftCollectionId, + item: T::NftItemId, + virtual_account: T::AccountId, + ) -> DispatchResult { + let own = Vec::new(); + let owners = BoundedVec::truncate_from(own); + let created = >::block_number(); + let token_id: ::AssetId = TokenId::::get().into(); + let rent_nbr = 0; + let ownership = Ownership:: { virtual_account, owners, created, token_id, rent_nbr }; + + Virtual::::insert(collection, item, ownership); + + Ok(()) + } +} \ No newline at end of file diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 15f1b683..dfcf45c8 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -69,6 +69,7 @@ pallet-nft = { version = "4.0.0-dev", default-features = false, path = "../palle pallet-onboarding = { version = "4.0.0-dev", default-features = false, path = "../pallets/onboarding" } pallet-council = { version = "4.0.0-dev", default-features = false, path = "../pallets/council" } pallet-finalizer = { version = "4.0.0-dev", default-features = false, path = "../pallets/finalizer" } +pallet-share_distributor = { version = "4.0.0-dev", default-features = false, path = "../pallets/share_distributor" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/polkadot-sdk", optional = true , tag = "polkadot-v1.1.0" } @@ -121,6 +122,7 @@ std = [ "pallet-assets/std", "pallet-nfts/std", "pallet-nfts-runtime-api/std", + "pallet-share_distributor/std" ### add new std ] runtime-benchmarks = [ @@ -147,6 +149,7 @@ runtime-benchmarks = [ "pallet-preimage/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", + "pallet-share_distributor/runtime-benchmarks" ### add new runtime-benchmarks ] try-runtime = [ @@ -172,5 +175,6 @@ try-runtime = [ "pallet-preimage/try-runtime", "pallet-democracy/try-runtime", "pallet-nfts/try-runtime", + "pallet-share_distributor/try-runtime" ### add new try-runtime ] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e2fb8a31..a41ecf09 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -60,6 +60,7 @@ pub use pallet_housing_fund; pub use pallet_onboarding; pub use pallet_council; use pallet_nft::NftPermissions; +pub use pallet_share_distributor; pub use pallet_nft::{self, Acc, CollectionId, ItemId, NftPermission}; // flag add pallet use @@ -303,6 +304,18 @@ impl pallet_council::Config for Runtime { //type WeightInfo = pallet_roles::weights::SubstrateWeight; } +parameter_types!{ + pub const AssetsFees: Balance = 25 * DOLLARS; + pub const MaxOwners:u32 = 20; +} + +impl pallet_share_distributor::Config for Runtime{ + type RuntimeEvent = RuntimeEvent; + type AssetId = codec::Compact; + type Fees = AssetsFees; + type MaxOwners = MaxOwners; +} + parameter_types! { pub const ProposalFee: Percent= Percent::from_percent(15); pub const SlashedFee: Percent = Percent::from_percent(10); @@ -676,6 +689,7 @@ construct_runtime!( OnboardingModule: pallet_onboarding, CouncilModule: pallet_council, FinalizerModule: pallet_finalizer, + ShareDistributorModule: pallet_share_distributor, // flag add pallet runtime } ); @@ -727,6 +741,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_roles, RolesModule] //[pallet_council, CouncilModule] + //[pallet_share_distributor,ShareDistributorModule] //[pallet_housing_fund, HousingFundModule] [pallet_identity, Identity] //[pallet_onboarding, onboardingModule]