From 3b5cf133375f6d7e8ca3c50a8023fcae8ee033be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20=C5=BBuk?= Date: Fri, 27 Sep 2024 15:48:33 +0200 Subject: [PATCH] Add eresidency required parameter to Assets --- Cargo.lock | 9 + liberland-extension/runtime/Cargo.toml | 4 + liberland-extension/runtime/src/lib.rs | 4 +- substrate/bin/node/runtime/src/lib.rs | 2 + substrate/frame/assets/Cargo.toml | 1 + substrate/frame/assets/src/benchmarking.rs | 16 + substrate/frame/assets/src/eresidency.rs | 39 +++ substrate/frame/assets/src/functions.rs | 7 + substrate/frame/assets/src/lib.rs | 54 +++ substrate/frame/assets/src/mock.rs | 7 + substrate/frame/assets/src/tests.rs | 60 ++++ substrate/frame/assets/src/types.rs | 6 + substrate/frame/assets/src/weights.rs | 48 +++ substrate/frame/democracy/Cargo.toml | 4 + substrate/frame/democracy/src/tests.rs | 36 ++ substrate/frame/elections-phragmen/Cargo.toml | 7 +- substrate/frame/elections-phragmen/src/lib.rs | 37 ++ .../frame/liberland-initializer/Cargo.toml | 3 + .../frame/liberland-initializer/src/lib.rs | 12 +- .../frame/liberland-legislation/Cargo.toml | 4 + .../frame/liberland-legislation/src/mock.rs | 37 ++ substrate/frame/liberland-traits/src/impls.rs | 9 + substrate/frame/liberland-traits/src/lib.rs | 5 + substrate/frame/llm/Cargo.toml | 3 + substrate/frame/llm/src/benchmarking.rs | 14 +- substrate/frame/llm/src/impl_fungible.rs | 2 +- substrate/frame/llm/src/lib.rs | 163 ++++++--- substrate/frame/llm/src/migrations.rs | 323 ------------------ substrate/frame/llm/src/mock.rs | 38 +++ substrate/frame/staking/Cargo.toml | 3 + substrate/frame/staking/src/mock.rs | 37 ++ 31 files changed, 610 insertions(+), 384 deletions(-) create mode 100644 substrate/frame/assets/src/eresidency.rs delete mode 100644 substrate/frame/llm/src/migrations.rs diff --git a/Cargo.lock b/Cargo.lock index 6205604eb1..a2a502426c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4489,6 +4489,8 @@ dependencies = [ "frame-support", "frame-system", "log", + "pallet-asset-conversion", + "pallet-assets", "pallet-contracts", "pallet-llm", "parity-scale-codec", @@ -6019,6 +6021,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "liberland-traits", "log", "pallet-balances", "parity-scale-codec", @@ -6247,6 +6250,7 @@ dependencies = [ "frame-system", "liberland-traits", "log", + "pallet-asset-conversion", "pallet-assets", "pallet-balances", "pallet-identity", @@ -6310,6 +6314,7 @@ dependencies = [ "frame-system", "liberland-traits", "log", + "pallet-asset-conversion", "pallet-assets", "pallet-balances", "pallet-identity", @@ -6398,6 +6403,7 @@ dependencies = [ "frame-system", "liberland-traits", "log", + "pallet-assets", "pallet-balances", "pallet-identity", "pallet-llm", @@ -6421,6 +6427,7 @@ dependencies = [ "frame-system", "liberland-traits", "log", + "pallet-asset-conversion", "pallet-assets", "pallet-balances", "pallet-democracy", @@ -6448,6 +6455,7 @@ dependencies = [ "hex-literal 0.3.4", "liberland-traits", "log", + "pallet-asset-conversion", "pallet-assets", "pallet-balances", "pallet-identity", @@ -6700,6 +6708,7 @@ dependencies = [ "frame-system", "liberland-traits", "log", + "pallet-asset-conversion", "pallet-assets", "pallet-authorship", "pallet-bags-list", diff --git a/liberland-extension/runtime/Cargo.toml b/liberland-extension/runtime/Cargo.toml index 2e2d7f8034..4bae6df2a4 100644 --- a/liberland-extension/runtime/Cargo.toml +++ b/liberland-extension/runtime/Cargo.toml @@ -19,6 +19,8 @@ frame-system = { default-features = false, tag = "polkadot-v1.1.0", git = "https log = { version = "0.4.17", default-features = false } pallet-llm = { default-features = false, path = "../../substrate/frame/llm" } +pallet-assets = { default-features = false, path = "../../substrate/frame/assets" } +pallet-asset-conversion = { default-features = false, tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } [features] default = ["std"] @@ -32,4 +34,6 @@ std = [ "frame-system/std", "log/std", "pallet-llm/std", + "pallet-assets/std", + "pallet-asset-conversion/std", ] \ No newline at end of file diff --git a/liberland-extension/runtime/src/lib.rs b/liberland-extension/runtime/src/lib.rs index ed2b224005..50ee7c8ba8 100644 --- a/liberland-extension/runtime/src/lib.rs +++ b/liberland-extension/runtime/src/lib.rs @@ -5,11 +5,13 @@ use log::{error, trace}; use pallet_contracts::chain_extension::{ChainExtension, Environment, Ext, InitState, RetVal}; use sp_runtime::DispatchError; +type BalanceOfAssets = ::Balance; + #[derive(Decode, Encode, MaxEncodedLen)] pub struct LLMForceTransferArguments { from: pallet_llm::LLMAccount, to: pallet_llm::LLMAccount, - amount: T::Balance, + amount: BalanceOfAssets, } /// Contract extension for the Liberland Chain diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 9290e50cc2..e0af3801f5 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1265,6 +1265,7 @@ impl pallet_assets::Config for Runtime { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = LLM; } ord_parameter_types! { @@ -1292,6 +1293,7 @@ impl pallet_assets::Config for Runtime { type CallbackHandle = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = LLM; } parameter_types! { diff --git a/substrate/frame/assets/Cargo.toml b/substrate/frame/assets/Cargo.toml index b10758e262..8c878c22a8 100644 --- a/substrate/frame/assets/Cargo.toml +++ b/substrate/frame/assets/Cargo.toml @@ -25,6 +25,7 @@ frame-support = { default-features = false, tag = "polkadot-v1.1.0", git = "http frame-system = { default-features = false, tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } frame-benchmarking = { default-features = false, optional = true, tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } sp-core = { default-features = false, tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } +liberland-traits = { default-features = false, path = "../liberland-traits" } [dev-dependencies] sp-std = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } diff --git a/substrate/frame/assets/src/benchmarking.rs b/substrate/frame/assets/src/benchmarking.rs index c9b0825542..e6a889b9e8 100644 --- a/substrate/frame/assets/src/benchmarking.rs +++ b/substrate/frame/assets/src/benchmarking.rs @@ -548,5 +548,21 @@ benchmarks_instance_pallet! { assert_last_event::(Event::Blocked { asset_id: asset_id.into(), who: caller }.into()); } + set_parameters { + let (asset_id, caller, _) = create_default_asset::(true); + let parameters = AssetParameters { eresidency_required: true }; + }: _(SystemOrigin::Signed(caller), asset_id, parameters) + verify { + assert_last_event::(Event::ParametersSet { asset_id: asset_id.into(), parameters }.into()); + } + + force_set_parameters { + let (asset_id, caller, _) = create_default_asset::(true); + let parameters = AssetParameters { eresidency_required: true }; + }: _(SystemOrigin::Root, asset_id, parameters) + verify { + assert_last_event::(Event::ParametersSet { asset_id: asset_id.into(), parameters }.into()); + } + impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test) } diff --git a/substrate/frame/assets/src/eresidency.rs b/substrate/frame/assets/src/eresidency.rs new file mode 100644 index 0000000000..9d0ba81d32 --- /dev/null +++ b/substrate/frame/assets/src/eresidency.rs @@ -0,0 +1,39 @@ +/* + +Copyright © 2024 Liberland + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +use crate::*; +use sp_runtime::DispatchResult; +use liberland_traits::CitizenshipChecker; +use frame_support::ensure; + +impl, I: 'static> Pallet { + pub fn do_set_parameters( + asset: T::AssetId, + parameters: AssetParameters, + maybe_check_owner: Option, + ) -> DispatchResult { + if let Some(check_owner) = maybe_check_owner { + let d = Asset::::get(&asset).ok_or(Error::::Unknown)?; + ensure!(d.owner == check_owner, Error::::NoPermission); + } + + Parameters::::insert(&asset, parameters); + Self::deposit_event(Event::ParametersSet { asset_id: asset, parameters }); + Ok(()) + } + + pub fn maybe_ensure_eresidency(asset: T::AssetId, who: &T::AccountId) -> DispatchResult { + let AssetParameters { eresidency_required } = Parameters::::get(asset); + if eresidency_required { + T::Citizenship::ensure_stocks_allowed(who)? + } + Ok(()) + } +} diff --git a/substrate/frame/assets/src/functions.rs b/substrate/frame/assets/src/functions.rs index c2c1b68390..f310e9f41e 100644 --- a/substrate/frame/assets/src/functions.rs +++ b/substrate/frame/assets/src/functions.rs @@ -19,6 +19,7 @@ use super::*; use frame_support::{defensive, traits::Get, BoundedVec}; +use liberland_traits::CitizenshipChecker; #[must_use] pub(super) enum DeadConsequence { @@ -135,6 +136,12 @@ impl, I: 'static> Pallet { if increase_supply && details.supply.checked_add(&amount).is_none() { return DepositConsequence::Overflow } + + let AssetParameters { eresidency_required } = Parameters::::get(&id); + if eresidency_required && T::Citizenship::ensure_stocks_allowed(who).is_err() { + return DepositConsequence::Blocked + } + if let Some(account) = Account::::get(id, who) { if account.status.is_blocked() { return DepositConsequence::Blocked diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 79e4fe3001..fb0204dc43 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -155,6 +155,7 @@ mod functions; mod impl_fungibles; mod impl_stored_map; mod types; +mod eresidency; pub use types::*; use scale_info::TypeInfo; @@ -322,6 +323,8 @@ pub mod pallet { /// Helper trait for benchmarks. #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper: BenchmarkHelper; + + type Citizenship: liberland_traits::CitizenshipChecker; } #[pallet::storage] @@ -368,6 +371,16 @@ pub mod pallet { ValueQuery, >; + #[pallet::storage] + /// Eresidency requirements of asset + pub(super) type Parameters, I: 'static = ()> = StorageMap< + _, + Blake2_128Concat, + T::AssetId, + AssetParameters, + ValueQuery, + >; + #[pallet::genesis_config] #[derive(frame_support::DefaultNoBound)] pub struct GenesisConfig, I: 'static = ()> { @@ -524,6 +537,11 @@ pub mod pallet { Touched { asset_id: T::AssetId, who: T::AccountId, depositor: T::AccountId }, /// Some account `who` was blocked. Blocked { asset_id: T::AssetId, who: T::AccountId }, + /// Asset Parameters set + ParametersSet { + asset_id: T::AssetId, + parameters: AssetParameters, + }, } #[pallet::error] @@ -1636,6 +1654,42 @@ pub mod pallet { Self::deposit_event(Event::::Blocked { asset_id: id, who }); Ok(()) } + + /// Set the parameters for an asset. + /// + /// Origin must be Signed and the sender should be the Owner of the asset `id`. + /// + /// Emits `ParametersSet`. + /// + /// Weight: `O(1)` + #[pallet::call_index(100)] + #[pallet::weight(T::WeightInfo::set_parameters())] + pub fn set_parameters( + origin: OriginFor, + id: T::AssetIdParameter, + parameters: AssetParameters, + ) -> DispatchResult { + let signer = ensure_signed(origin)?; + let id: T::AssetId = id.into(); + Self::do_set_parameters(id, parameters, Some(signer)) + } + + /// Force set the parameters for an asset. + /// + /// Origin must be ForceOrigin. + /// + /// Weight: `O(1)` + #[pallet::call_index(101)] + #[pallet::weight(T::WeightInfo::force_set_parameters())] + pub fn force_set_parameters( + origin: OriginFor, + id: T::AssetIdParameter, + parameters: AssetParameters, + ) -> DispatchResult { + T::ForceOrigin::ensure_origin(origin)?; + let id: T::AssetId = id.into(); + Self::do_set_parameters(id, parameters, None) + } } /// Implements [`AccountTouch`] trait. diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs index 32ad02da90..2dbefef7b8 100644 --- a/substrate/frame/assets/src/mock.rs +++ b/substrate/frame/assets/src/mock.rs @@ -31,6 +31,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; +use liberland_traits::MockCitizenshipChecker; type Block = frame_system::mocking::MockBlock; @@ -131,6 +132,11 @@ impl AssetsCallbackHandle { } } +parameter_types! { + pub MockCitizenOne: AccountId = 100u64; + pub MockCitizenTwo: AccountId = 101u64; +} + impl Config for Test { type RuntimeEvent = RuntimeEvent; type Balance = u64; @@ -152,6 +158,7 @@ impl Config for Test { type RemoveItemsLimit = ConstU32<5>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = MockCitizenshipChecker; } use std::collections::HashMap; diff --git a/substrate/frame/assets/src/tests.rs b/substrate/frame/assets/src/tests.rs index 06d4ec1211..194848f5cb 100644 --- a/substrate/frame/assets/src/tests.rs +++ b/substrate/frame/assets/src/tests.rs @@ -22,6 +22,7 @@ use crate::{mock::*, Error}; use frame_support::{ assert_noop, assert_ok, dispatch::GetDispatchInfo, + error::BadOrigin, traits::{fungibles::InspectEnumerable, tokens::Preservation::Protect, Currency}, }; use pallet_balances::Error as BalancesError; @@ -1775,3 +1776,62 @@ fn asset_destroy_refund_existence_deposit() { assert_eq!(Balances::reserved_balance(&admin), 0); }); } + +#[test] +fn only_owner_can_set_parameters() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); + let admin_origin = RuntimeOrigin::signed(1); + assert_ok!(Assets::set_parameters(admin_origin, 0, AssetParameters { eresidency_required: true })); + + let nonadmin_origin = RuntimeOrigin::signed(2); + assert_noop!( + Assets::set_parameters(nonadmin_origin, 0, AssetParameters { eresidency_required: true }), + Error::::NoPermission + ); + }); +} + +#[test] +fn only_root_can_force_set_parameters() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); + let root_origin = RuntimeOrigin::root(); + assert_ok!(Assets::force_set_parameters(root_origin, 0, AssetParameters { eresidency_required: true })); + + let admin_origin = RuntimeOrigin::signed(1); + assert_noop!( + Assets::force_set_parameters(admin_origin, 0, AssetParameters { eresidency_required: true }), + BadOrigin + ); + }); +} + +#[test] +fn eresident_can_receive_eresidency_only_asset() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); + let root_origin = RuntimeOrigin::root(); + assert_ok!(Assets::force_set_parameters(root_origin, 0, AssetParameters { eresidency_required: true })); + assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 100, 100)); + assert_ok!(Assets::transfer(RuntimeOrigin::signed(100), 0, 101, 100)); + }); +} + +#[test] +fn non_eresident_cant_receive_eresidency_only_asset() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); + assert_ok!(Assets::force_set_parameters(RuntimeOrigin::root(), 0, AssetParameters { eresidency_required: true })); + assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 100, 100)); + + assert_noop!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100), TokenError::Blocked); + assert_noop!(Assets::transfer(RuntimeOrigin::signed(100), 0, 1, 100), TokenError::Blocked); + assert_noop!(Assets::transfer_keep_alive(RuntimeOrigin::signed(100), 0, 1, 50), TokenError::Blocked); + assert_noop!(Assets::force_transfer(RuntimeOrigin::signed(1), 0, 100, 1, 100), TokenError::Blocked); + + Balances::make_free_balance_be(&100, 100); + assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(100), 0, 1, 50)); + assert_noop!(Assets::transfer_approved(RuntimeOrigin::signed(1), 0, 100, 1, 50), TokenError::Blocked); + }); +} \ No newline at end of file diff --git a/substrate/frame/assets/src/types.rs b/substrate/frame/assets/src/types.rs index 67f9bf07f5..5370511128 100644 --- a/substrate/frame/assets/src/types.rs +++ b/substrate/frame/assets/src/types.rs @@ -317,3 +317,9 @@ where .saturating_mul_int(balance)) } } + +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct AssetParameters { + /// Is eresidency required to receive the asset + pub(super) eresidency_required: bool, +} \ No newline at end of file diff --git a/substrate/frame/assets/src/weights.rs b/substrate/frame/assets/src/weights.rs index f20f7e317c..14642a705a 100644 --- a/substrate/frame/assets/src/weights.rs +++ b/substrate/frame/assets/src/weights.rs @@ -84,6 +84,8 @@ pub trait WeightInfo { fn refund() -> Weight; fn refund_other() -> Weight; fn block() -> Weight; + fn set_parameters() -> Weight; + fn force_set_parameters() -> Weight; } /// Weights for pallet_assets using the Substrate node and recommended hardware. @@ -525,6 +527,29 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Parameters` (r:0 w:1) + /// Proof: `Assets::Parameters` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`) + fn set_parameters() -> Weight { + // Proof Size summary in bytes: + // Measured: `348` + // Estimated: `3675` + // Minimum execution time: 18_124_000 picoseconds. + Weight::from_parts(18_495_000, 3675) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Assets::Parameters` (r:0 w:1) + /// Proof: `Assets::Parameters` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`) + fn force_set_parameters() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 11_723_000 picoseconds. + Weight::from_parts(12_263_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests @@ -965,4 +990,27 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Parameters` (r:0 w:1) + /// Proof: `Assets::Parameters` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`) + fn set_parameters() -> Weight { + // Proof Size summary in bytes: + // Measured: `348` + // Estimated: `3675` + // Minimum execution time: 18_124_000 picoseconds. + Weight::from_parts(18_495_000, 3675) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Assets::Parameters` (r:0 w:1) + /// Proof: `Assets::Parameters` (`max_values`: None, `max_size`: Some(21), added: 2496, mode: `MaxEncodedLen`) + fn force_set_parameters() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 11_723_000 picoseconds. + Weight::from_parts(12_263_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/substrate/frame/democracy/Cargo.toml b/substrate/frame/democracy/Cargo.toml index 55645f3af5..1a85e5f578 100644 --- a/substrate/frame/democracy/Cargo.toml +++ b/substrate/frame/democracy/Cargo.toml @@ -36,6 +36,7 @@ liberland-traits = { path = "../liberland-traits", default-features = false} pallet-balances = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } pallet-scheduler = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } pallet-preimage = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } +pallet-asset-conversion = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } pallet-assets = { path = "../assets" } pallet-nfts = { path = "../nfts" } @@ -58,6 +59,7 @@ std = [ "pallet-llm/std", "pallet-nfts/std", "pallet-liberland-initializer/std", + "pallet-asset-conversion/std", "liberland-traits/std", ] runtime-benchmarks = [ @@ -71,6 +73,7 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", "pallet-liberland-initializer/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", "liberland-traits/runtime-benchmarks", ] try-runtime = [ @@ -80,5 +83,6 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-preimage/try-runtime", "pallet-scheduler/try-runtime", + "pallet-asset-conversion/runtime-benchmarks", "sp-runtime/try-runtime", ] \ No newline at end of file diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index 52a3fdde91..7e2d389403 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -31,6 +31,7 @@ use frame_support::{ OnInitialize, SortedMembers, Everything, }, weights::Weight, + PalletId, }; use frame_system::{EnsureRoot, EnsureSigned, EnsureSignedBy}; use sp_core::H256; @@ -41,6 +42,7 @@ use sp_runtime::{ Perbill, Permill, }; +use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; mod cancellation; mod decoders; @@ -73,8 +75,41 @@ frame_support::construct_runtime!( Identity: pallet_identity::{Pallet, Call, Storage, Event}, LLM: pallet_llm::{Pallet, Call, Storage, Config, Event}, LiberlandInitializer: pallet_liberland_initializer, + AssetConversion: pallet_asset_conversion, } ); +parameter_types! { + pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); + pub AllowMultiAssetPools: bool = true; + pub const PoolSetupFee: u64 = 1; + pub const MintMinLiquidity: u64 = 100; + pub const LiquidityWithdrawalFee: Permill = Permill::from_parts(0); +} + +impl pallet_asset_conversion::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type AssetBalance = ::Balance; + type HigherPrecisionBalance = u128; + type Assets = Assets; + type Balance = u64; + type PoolAssets = Assets; + type AssetId = ::AssetId; + type MultiAssetId = NativeOrAssetId; + type PoolAssetId = ::AssetId; + type PalletId = AssetConversionPalletId; + type LPFee = ConstU32<5>; // means 0.5%; + type PoolSetupFee = PoolSetupFee; + type PoolSetupFeeReceiver = (); + type LiquidityWithdrawalFee = LiquidityWithdrawalFee; + type WeightInfo = pallet_asset_conversion::weights::SubstrateWeight; + type AllowMultiAssetPools = AllowMultiAssetPools; + type MaxSwapPathLength = ConstU32<4>; + type MintMinLiquidity = MintMinLiquidity; + type MultiAssetIdConverter = NativeOrAssetIdConverter; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; type Balance = u64; @@ -96,6 +131,7 @@ impl pallet_assets::Config for Test { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = (); } // Test that a fitlered call can be dispatched. diff --git a/substrate/frame/elections-phragmen/Cargo.toml b/substrate/frame/elections-phragmen/Cargo.toml index 1add4b7387..3dab86c999 100644 --- a/substrate/frame/elections-phragmen/Cargo.toml +++ b/substrate/frame/elections-phragmen/Cargo.toml @@ -41,6 +41,7 @@ pallet-nfts = { path = "../nfts" } sp-tracing = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } substrate-test-utils = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } sp-core = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } +pallet-asset-conversion = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } [features] default = [ "std" ] @@ -61,6 +62,7 @@ std = [ "pallet-llm/std", "pallet-nfts/std", "pallet-liberland-initializer/std", + "pallet-asset-conversion/std", "liberland-traits/std", "sp-tracing/std", ] @@ -70,6 +72,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", "pallet-liberland-initializer/runtime-benchmarks", "liberland-traits/runtime-benchmarks", ] @@ -77,7 +80,5 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-llm/try-runtime", - "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks", + "pallet-asset-conversion/try-runtime", ] diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index f0f1fe42c8..427f17dfe9 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -1269,6 +1269,7 @@ mod tests { dispatch::DispatchResultWithPostInfo, parameter_types, traits::{ConstU32, ConstU64}, + PalletId, }; use frame_system::ensure_signed; use sp_runtime::{ @@ -1286,6 +1287,7 @@ mod tests { use frame_support::traits::{AsEnsureOriginWithArg, OnInitialize}; use substrate_test_utils::assert_eq_uvec; + use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; type Block = frame_system::mocking::MockBlock; @@ -1300,6 +1302,7 @@ mod tests { LLM: pallet_llm::{Pallet, Call, Storage, Config, Event}, LiberlandInitializer: pallet_liberland_initializer, Elections: pallet_elections_phragmen::{Pallet, Call, Event, Config}, + AssetConversion: pallet_asset_conversion, } ); @@ -1402,6 +1405,40 @@ mod tests { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = (); + } + + parameter_types! { + pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); + pub AllowMultiAssetPools: bool = true; + pub const PoolSetupFee: u64 = 1; + pub const MintMinLiquidity: u64 = 100; + pub const LiquidityWithdrawalFee: Permill = Permill::from_parts(0); + } + + impl pallet_asset_conversion::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type AssetBalance = ::Balance; + type HigherPrecisionBalance = u128; + type Assets = Assets; + type Balance = u64; + type PoolAssets = Assets; + type AssetId = ::AssetId; + type MultiAssetId = NativeOrAssetId; + type PoolAssetId = ::AssetId; + type PalletId = AssetConversionPalletId; + type LPFee = ConstU32<5>; // means 0.5%; + type PoolSetupFee = PoolSetupFee; + type PoolSetupFeeReceiver = (); + type LiquidityWithdrawalFee = LiquidityWithdrawalFee; + type WeightInfo = pallet_asset_conversion::weights::SubstrateWeight; + type AllowMultiAssetPools = AllowMultiAssetPools; + type MaxSwapPathLength = ConstU32<4>; + type MintMinLiquidity = MintMinLiquidity; + type MultiAssetIdConverter = NativeOrAssetIdConverter; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! { diff --git a/substrate/frame/liberland-initializer/Cargo.toml b/substrate/frame/liberland-initializer/Cargo.toml index 105dc6b2c4..885d6bafae 100644 --- a/substrate/frame/liberland-initializer/Cargo.toml +++ b/substrate/frame/liberland-initializer/Cargo.toml @@ -31,6 +31,7 @@ pallet-identity = { default-features = false, path = "../identity" } pallet-nfts = { default-features = false, path = "../nfts" } pallet-registry = { default-features = false, path = "../registry" } pallet-llm = { default-features = false, path = "../llm" } +pallet-assets = { default-features = false, path = "../assets" } liberland-traits = { path = "../liberland-traits", default-features = false} [dev-dependencies] @@ -47,6 +48,7 @@ std = [ "pallet-nfts/std", "pallet-registry/std", "pallet-llm/std", + "pallet-assets/std", "log/std", "sp-io/std", "sp-runtime/std", @@ -61,6 +63,7 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "pallet-llm/try-runtime", + "pallet-assets/try-runtime", "pallet-identity/try-runtime", "pallet-registry/try-runtime", "pallet-nfts/try-runtime", diff --git a/substrate/frame/liberland-initializer/src/lib.rs b/substrate/frame/liberland-initializer/src/lib.rs index 472f1dcdf7..ff7229f287 100644 --- a/substrate/frame/liberland-initializer/src/lib.rs +++ b/substrate/frame/liberland-initializer/src/lib.rs @@ -79,10 +79,12 @@ pub mod pallet { use ::{frame_support::traits::Currency, sp_runtime::traits::Bounded}; #[cfg(any(test, feature = "runtime-benchmarks"))] - type BalanceOf = <::Currency as Currency< + type BalanceOfIdentity = <::Currency as Currency< ::AccountId, >>::Balance; + type BalanceOfAssets = ::Balance; + #[pallet::pallet] pub struct Pallet(_); @@ -95,7 +97,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { pub citizenship_registrar: Option, - pub initial_citizens: Vec<(T::AccountId, T::Balance, T::Balance)>, + pub initial_citizens: Vec<(T::AccountId, BalanceOfAssets, BalanceOfAssets)>, pub land_registrar: Option, pub metaverse_land_registrar: Option, pub asset_registrar: Option, @@ -233,12 +235,12 @@ pub mod pallet { } /// Sends `amount` of LLM to `citizen`. - fn give_llm(citizen: T::AccountId, amount: T::Balance) { + fn give_llm(citizen: T::AccountId, amount: BalanceOfAssets) { pallet_llm::Pallet::::transfer_from_treasury(citizen, amount).unwrap(); } /// Politipools `amount` of `citizen`'s LLM. - fn politics_lock_llm(citizen: T::AccountId, amount: T::Balance) { + fn politics_lock_llm(citizen: T::AccountId, amount: BalanceOfAssets) { let origin = frame_system::RawOrigin::Signed(citizen.clone()).into(); pallet_llm::Pallet::::politics_lock(origin, amount).unwrap(); } @@ -259,7 +261,7 @@ pub mod pallet { }; if ::Currency::free_balance(&account) == 0u8.into() { - let balance = BalanceOf::::max_value() / 2u8.into(); + let balance = BalanceOfIdentity::::max_value() / 2u8.into(); ::Currency::make_free_balance_be(&account, balance); } diff --git a/substrate/frame/liberland-legislation/Cargo.toml b/substrate/frame/liberland-legislation/Cargo.toml index 1f5e861e33..47e4acf0c9 100644 --- a/substrate/frame/liberland-legislation/Cargo.toml +++ b/substrate/frame/liberland-legislation/Cargo.toml @@ -37,6 +37,7 @@ pallet-liberland-initializer = { path = "../liberland-initializer" } pallet-democracy = { path = "../democracy" } pallet-nfts = { path = "../nfts" } pallet-identity = { path = "../identity" } +pallet-asset-conversion = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } [features] default = ["std"] @@ -49,6 +50,7 @@ std = [ "pallet-llm/std", "pallet-democracy/std", "pallet-nfts/std", + "pallet-asset-conversion/std", "log/std", "sp-io/std", "sp-runtime/std", @@ -59,6 +61,8 @@ std = [ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", + "pallet-llm/runtime-benchmarks", "pallet-liberland-initializer/runtime-benchmarks", "liberland-traits/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", diff --git a/substrate/frame/liberland-legislation/src/mock.rs b/substrate/frame/liberland-legislation/src/mock.rs index 710aec6568..b10d72625e 100644 --- a/substrate/frame/liberland-legislation/src/mock.rs +++ b/substrate/frame/liberland-legislation/src/mock.rs @@ -8,9 +8,11 @@ use frame_support::{ AsEnsureOriginWithArg, ConstU16, ConstU32, ConstU64, EitherOfDiverse, EqualPrivilegeOnly, Everything, }, + PalletId, }; use frame_system as system; use frame_system::{EnsureRoot, EnsureSigned, EnsureSignedBy}; +use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; use pallet_balances::AccountData; use sp_core::H256; use sp_runtime::{ @@ -35,6 +37,7 @@ frame_support::construct_runtime!( LiberlandInitializer: pallet_liberland_initializer, Scheduler: pallet_scheduler, Democracy: pallet_democracy, + AssetConversion: pallet_asset_conversion, } ); @@ -199,6 +202,7 @@ impl pallet_assets::Config for Test { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = (); } parameter_types! { @@ -270,6 +274,39 @@ impl pallet_liberland_legislation::Config for Test { type WeightInfo = (); } +parameter_types! { + pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); + pub AllowMultiAssetPools: bool = true; + pub const PoolSetupFee: u64 = 1; + pub const MintMinLiquidity: u64 = 100; + pub const LiquidityWithdrawalFee: Permill = Permill::from_parts(0); +} + +impl pallet_asset_conversion::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type AssetBalance = ::Balance; + type HigherPrecisionBalance = u128; + type Assets = Assets; + type Balance = u64; + type PoolAssets = Assets; + type AssetId = ::AssetId; + type MultiAssetId = NativeOrAssetId; + type PoolAssetId = ::AssetId; + type PalletId = AssetConversionPalletId; + type LPFee = ConstU32<5>; // means 0.5%; + type PoolSetupFee = PoolSetupFee; + type PoolSetupFeeReceiver = (); + type LiquidityWithdrawalFee = LiquidityWithdrawalFee; + type WeightInfo = pallet_asset_conversion::weights::SubstrateWeight; + type AllowMultiAssetPools = AllowMultiAssetPools; + type MaxSwapPathLength = ConstU32<4>; + type MintMinLiquidity = MintMinLiquidity; + type MultiAssetIdConverter = NativeOrAssetIdConverter; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + // Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); diff --git a/substrate/frame/liberland-traits/src/impls.rs b/substrate/frame/liberland-traits/src/impls.rs index 6b94d69f49..a7c92dc496 100644 --- a/substrate/frame/liberland-traits/src/impls.rs +++ b/substrate/frame/liberland-traits/src/impls.rs @@ -12,6 +12,11 @@ where C1: Get, C2: Get, { + fn ensure_stocks_allowed(account: &T) -> Result<(), DispatchError> { + ensure!(Self::is_citizen(account), DispatchError::Other("NotCitizen")); + Ok(()) + } + fn ensure_politics_allowed(account: &T) -> Result<(), DispatchError> { ensure!(Self::is_citizen(account), DispatchError::Other("NotCitizen")); Ok(()) @@ -48,6 +53,10 @@ impl OnLLMPoliticsUnlock for () { /// Noop implementation of CitizenshipChecker - mostly to be used in tests to /// prevent circular dependencies impl CitizenshipChecker for () { + fn ensure_stocks_allowed(_account: &T) -> Result<(), DispatchError> { + Ok(()) + } + fn ensure_politics_allowed(_account: &T) -> Result<(), DispatchError> { Ok(()) } diff --git a/substrate/frame/liberland-traits/src/lib.rs b/substrate/frame/liberland-traits/src/lib.rs index 38dbb5ea86..9c21fc39c7 100644 --- a/substrate/frame/liberland-traits/src/lib.rs +++ b/substrate/frame/liberland-traits/src/lib.rs @@ -28,6 +28,11 @@ pub trait LLM { /// trait for more abstract methods that take data from multiple sources pub trait CitizenshipChecker { + /// Checks if account can receive stocks. Accounts needs to: + /// * have valid citizen or eresident identity + /// * have a KnownGood judgement + fn ensure_stocks_allowed(account: &AccountId) -> Result<(), DispatchError>; + /// Checks if account has politics allowed. For politics to be allowed, account needs to: /// * have LLM politipooled /// * not have LLM Electionlock diff --git a/substrate/frame/llm/Cargo.toml b/substrate/frame/llm/Cargo.toml index 82761b5776..caddd4e1be 100644 --- a/substrate/frame/llm/Cargo.toml +++ b/substrate/frame/llm/Cargo.toml @@ -30,6 +30,7 @@ sp-runtime = { default-features = false, tag = "polkadot-v1.1.0", git = "https:/ pallet-assets = { path = "../assets", default-features = false } pallet-balances = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk", default-features = false } pallet-identity = { path = "../identity", default-features = false } +pallet-asset-conversion = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk", default-features = false } liberland-traits = { path = "../liberland-traits", default-features = false} @@ -51,10 +52,12 @@ std = [ "sp-runtime/std", "sp-std/std", "liberland-traits/std", + "pallet-asset-conversion/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", "liberland-traits/runtime-benchmarks", ] try-runtime = ["frame-support/try-runtime"] diff --git a/substrate/frame/llm/src/benchmarking.rs b/substrate/frame/llm/src/benchmarking.rs index 277baf851a..529acc53db 100644 --- a/substrate/frame/llm/src/benchmarking.rs +++ b/substrate/frame/llm/src/benchmarking.rs @@ -22,7 +22,7 @@ const SEED: u32 = 0; benchmarks! { politics_lock { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 100u8.into(); + let amount: BalanceOfAssets = 100u8.into(); LLM::::transfer_from_treasury(user.clone(), amount.clone()).unwrap(); let origin = RawOrigin::Signed(user.clone()); assert_eq!(LLMPolitics::::get(&user), 0u8.into()); @@ -33,7 +33,7 @@ benchmarks! { politics_unlock { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 10000u32.into(); + let amount: BalanceOfAssets = 10000u32.into(); LLM::::transfer_from_treasury(user.clone(), amount.clone()).unwrap(); let origin = RawOrigin::Signed(user.clone()); LLM::::politics_lock(origin.clone().into(), amount.clone()).unwrap(); @@ -45,7 +45,7 @@ benchmarks! { treasury_llm_transfer { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 100u32.into(); + let amount: BalanceOfAssets = 100u32.into(); assert_eq!(LLM::::balance(user.clone()), 0u8.into()); }: _(RawOrigin::Root, user.clone(), amount.clone()) verify { @@ -54,7 +54,7 @@ benchmarks! { treasury_llm_transfer_to_politipool { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 100u32.into(); + let amount: BalanceOfAssets = 100u32.into(); assert_eq!(LLMPolitics::::get(&user), 0u8.into()); }: _(RawOrigin::Root, user.clone(), amount.clone()) verify { @@ -63,7 +63,7 @@ benchmarks! { send_llm_to_politipool { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 100u8.into(); + let amount: BalanceOfAssets = 100u8.into(); LLM::::transfer_from_treasury(user.clone(), amount.clone()).unwrap(); let origin = RawOrigin::Signed(user.clone()); @@ -76,7 +76,7 @@ benchmarks! { send_llm { let user: T::AccountId = account("user", 0, SEED); - let amount: T::Balance = 100u8.into(); + let amount: BalanceOfAssets = 100u8.into(); LLM::::transfer_from_treasury(user.clone(), amount.clone()).unwrap(); let origin = RawOrigin::Signed(user.clone()); @@ -114,7 +114,7 @@ benchmarks! { force_transfer { let user: T::AccountId = account("user", 0, SEED); let user2: T::AccountId = account("user", 1, SEED); - let amount: T::Balance = 10000u32.into(); + let amount: BalanceOfAssets = 10000u32.into(); LLM::::transfer_from_treasury(user.clone(), amount.clone()).unwrap(); LLM::::set_courts(RawOrigin::Root.into(), vec![user.clone()].try_into().unwrap()).unwrap(); let origin = RawOrigin::Signed(user.clone()); diff --git a/substrate/frame/llm/src/impl_fungible.rs b/substrate/frame/llm/src/impl_fungible.rs index 0b197fedaf..97b3042a04 100644 --- a/substrate/frame/llm/src/impl_fungible.rs +++ b/substrate/frame/llm/src/impl_fungible.rs @@ -11,7 +11,7 @@ use frame_support::{ }; impl Inspect for Pallet { - type Balance = T::Balance; + type Balance = BalanceOfAssets; fn total_issuance() -> Self::Balance { let id = Self::llm_id(); diff --git a/substrate/frame/llm/src/lib.rs b/substrate/frame/llm/src/lib.rs index ef7021df0a..4a3ac74c56 100644 --- a/substrate/frame/llm/src/lib.rs +++ b/substrate/frame/llm/src/lib.rs @@ -9,7 +9,6 @@ pub mod weights; pub use weights::WeightInfo; mod impl_fungible; -pub mod migrations; /// Liberland Merit Pallet /* @@ -23,9 +22,10 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I */ use frame_support::traits::Currency; type Assets = pallet_assets::Pallet; -type BalanceOf = <::Currency as Currency< +type BalanceOfIdentity = <::Currency as Currency< ::AccountId, >>::Balance; +type BalanceOfAssets = ::Balance; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; @@ -51,6 +51,7 @@ pub mod pallet { }; use frame_system::{ensure_signed, pallet_prelude::*}; use liberland_traits::{CitizenshipChecker, OnLLMPoliticsUnlock, LLM}; + use pallet_identity::{Data, Data::Raw, Judgement::KnownGood}; use scale_info::prelude::vec; use sp_runtime::{ traits::{AccountIdConversion, StaticLookup}, @@ -69,7 +70,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn llm_politics)] pub(super) type LLMPolitics = - StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOfAssets, ValueQuery>; /// block number until which account can't do another `politics_unlock` #[pallet::storage] @@ -145,7 +146,10 @@ pub mod pallet { #[pallet::config] pub trait Config: - pallet_assets::Config + frame_system::Config + pallet_identity::Config + pallet_assets::Config + + frame_system::Config + + pallet_identity::Config + + pallet_asset_conversion::Config { /// The overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -206,6 +210,8 @@ pub mod pallet { NoPolLLM, /// Not a Citizen NonCitizen, + /// Not a eresident + NonEResident, /// Temporary locked after unpooling LLM Locked, /// Caller isn't an authorized court @@ -240,7 +246,7 @@ pub mod pallet { /// * `Transferred` from `pallet-assets` #[pallet::call_index(0)] #[pallet::weight(::WeightInfo::politics_lock())] - pub fn politics_lock(origin: OriginFor, amount: T::Balance) -> DispatchResult { + pub fn politics_lock(origin: OriginFor, amount: BalanceOfAssets) -> DispatchResult { let sender = ensure_signed(origin.clone())?; Self::do_politics_lock(sender, amount)?; Ok(()) @@ -267,7 +273,7 @@ pub mod pallet { let current_block_number = frame_system::Pallet::::block_number(); ensure!(current_block_number > Withdrawlock::::get(&sender), Error::::Gottawait); - let ten_percent: T::Balance = Self::get_unlock_amount(politics_balance)?; + let ten_percent: BalanceOfAssets = Self::get_unlock_amount(politics_balance)?; Self::transfer_from_politipool(sender.clone(), ten_percent)?; LLMPolitics::::mutate(&sender, |b| *b -= ten_percent); @@ -294,7 +300,7 @@ pub mod pallet { pub fn treasury_llm_transfer( origin: OriginFor, to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { T::SenateOrigin::ensure_origin(origin)?; Self::transfer_from_treasury(to_account, amount) @@ -312,7 +318,7 @@ pub mod pallet { pub fn treasury_llm_transfer_to_politipool( origin: OriginFor, to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { T::SenateOrigin::ensure_origin(origin)?; @@ -331,7 +337,7 @@ pub mod pallet { pub fn send_llm_to_politipool( origin: OriginFor, to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let sender: T::AccountId = ensure_signed(origin)?; @@ -351,7 +357,7 @@ pub mod pallet { pub fn send_llm( origin: OriginFor, to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let sender = ensure_signed(origin.clone())?; Self::transfer(sender, to_account, amount) @@ -403,7 +409,7 @@ pub mod pallet { origin: OriginFor, from: LLMAccount, to: LLMAccount, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let caller: T::AccountId = ensure_signed(origin)?; ensure!(Courts::::get().contains(&caller), Error::::NotCourt); @@ -453,19 +459,19 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// New LLM has been released - ReleasedLLM(T::AccountId, T::Balance), + ReleasedLLM(T::AccountId, BalanceOfAssets), /// New LLM has been created - LLMCreated(T::AccountId, T::Balance), // acountid, amount + LLMCreated(T::AccountId, BalanceOfAssets), // acountid, amount /// X amount of LLM has been unlocked - LLMPoliticsLocked(T::AccountId, T::Balance), + LLMPoliticsLocked(T::AccountId, BalanceOfAssets), /// sent to user account, amount - LLMPoliticsUnlocked(T::AccountId, T::Balance), + LLMPoliticsUnlocked(T::AccountId, BalanceOfAssets), /// Remark Remarked(RemarkData), } impl Pallet { - fn do_politics_lock(account: T::AccountId, amount: T::Balance) -> DispatchResult { + fn do_politics_lock(account: T::AccountId, amount: BalanceOfAssets) -> DispatchResult { Self::do_transfer_to_politipool(account.clone(), amount)?; LLMPolitics::::mutate(account.clone(), |b| *b += amount); Self::deposit_event(Event::::LLMPoliticsLocked(account, amount)); @@ -478,11 +484,11 @@ pub mod pallet { init_account } - pub fn balance(account: T::AccountId) -> T::Balance { + pub fn balance(account: T::AccountId) -> BalanceOfAssets { Assets::::balance(Self::llm_id().into(), account) } - fn get_unlock_amount(balance: T::Balance) -> Result> { + fn get_unlock_amount(balance: BalanceOfAssets) -> Result, Error> { let factor = T::UnlockFactor::get(); let amount = factor.mul_floor(balance); amount.try_into().map_err(|_| Error::::InvalidAmount) @@ -491,7 +497,7 @@ pub mod pallet { pub(super) fn transfer( from_account: T::AccountId, to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let origin = frame_system::RawOrigin::Signed(from_account.clone()).into(); Assets::::transfer( @@ -504,7 +510,7 @@ pub mod pallet { fn do_transfer_to_politipool( from_account: T::AccountId, - amount_balance: T::Balance, + amount_balance: BalanceOfAssets, ) -> DispatchResult { let politipool_account = Self::get_llm_politipool_account(); Self::transfer(from_account, politipool_account, amount_balance) @@ -512,7 +518,7 @@ pub mod pallet { fn transfer_from_politipool( to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let politipool_account = Self::get_llm_politipool_account(); Self::transfer(politipool_account, to_account, amount) @@ -520,7 +526,10 @@ pub mod pallet { /// Transfer `amount` LLM to `to_account` from vault /// Used in tests. - pub fn transfer_from_vault(to_account: T::AccountId, amount: T::Balance) -> DispatchResult { + pub fn transfer_from_vault( + to_account: T::AccountId, + amount: BalanceOfAssets, + ) -> DispatchResult { let vault = Self::get_llm_vault_account(); Self::transfer(vault, to_account, amount) } @@ -529,7 +538,7 @@ pub mod pallet { /// Used in liberland-initializer and in tests. pub fn transfer_from_treasury( to_account: T::AccountId, - amount: T::Balance, + amount: BalanceOfAssets, ) -> DispatchResult { let treasury = Self::get_llm_treasury_account(); Self::transfer(treasury, to_account, amount) @@ -543,7 +552,7 @@ pub mod pallet { let asset_supply = Assets::::total_supply(asset_id.clone()); ensure!(asset_supply == 0u8.into(), Error::::AssetExists); // if the asset supply is zero == that means it is not been created and we can create - let min_balance: T::Balance = 1u8.into(); + let min_balance: BalanceOfAssets = 1u8.into(); let decimals: u8 = 12u8; Assets::::force_create( origin.clone(), @@ -599,7 +608,7 @@ pub mod pallet { PalletId(*b"polilock").into_account_truncating() } - fn get_release_amount() -> Result> { + fn get_release_amount() -> Result, Error> { let asset_id = Self::llm_id().into(); let vault_account = Self::get_llm_vault_account(); let unreleased_amount = Assets::::balance(asset_id, vault_account); @@ -626,7 +635,7 @@ pub mod pallet { } /// Release tokens to the treasury account. Sends tokens from the llm/vault to the treasury - fn release_tokens_from_vault(amount: T::Balance) -> DispatchResult { + fn release_tokens_from_vault(amount: BalanceOfAssets) -> DispatchResult { let treasury = Self::get_llm_treasury_account(); Self::transfer_from_vault(treasury.clone(), amount)?; @@ -636,7 +645,7 @@ pub mod pallet { } } - impl LLM for Pallet { + impl LLM> for Pallet { fn check_pooled_llm(account: &T::AccountId) -> bool { let minimum = match T::CitizenshipMinimumPooledLLM::get().try_into() { Ok(m) => m, @@ -654,29 +663,50 @@ pub mod pallet { true } - fn get_politi_pooled_amount() -> T::Balance { + fn get_politi_pooled_amount() -> BalanceOfAssets { let politipool_account = Self::get_llm_politipool_account(); Self::balance(politipool_account) } - fn get_llm_politics(account: &T::AccountId) -> T::Balance { + fn get_llm_politics(account: &T::AccountId) -> BalanceOfAssets { LLMPolitics::::get(account) } } impl Pallet { - fn is_known_good_identity( + fn is_citizen_identity( reg: &pallet_identity::Registration< - BalanceOf, + BalanceOfIdentity, T::MaxRegistrars, T::MaxAdditionalFields, >, ) -> bool { - use pallet_identity::{Data, Data::Raw, Judgement::KnownGood}; - let citizen_key = Raw(b"citizen".to_vec().try_into().unwrap()); let is_citizen_field_set = matches!(reg.info.additional.iter().find(|v| v.0 == citizen_key), Some(x) if x.1 != Data::None); + is_citizen_field_set + } + + fn is_eresident_identity( + reg: &pallet_identity::Registration< + BalanceOfIdentity, + T::MaxRegistrars, + T::MaxAdditionalFields, + >, + ) -> bool { + let eresident_key = Raw(b"eresident".to_vec().try_into().unwrap()); + let is_eresident_field_set = matches!(reg.info.additional.iter().find(|v| v.0 == eresident_key), Some(x) if x.1 != Data::None); + + is_eresident_field_set + } + + fn is_eligible_identity( + reg: &pallet_identity::Registration< + BalanceOfIdentity, + T::MaxRegistrars, + T::MaxAdditionalFields, + >, + ) -> bool { let current_block_number = frame_system::Pallet::::block_number(); let eligible_on_key = Raw(b"eligible_on".to_vec().try_into().unwrap()); let eligible_on = match reg.info.additional.iter().find(|v| v.0 == eligible_on_key) { @@ -690,41 +720,86 @@ pub mod pallet { let is_eligible = matches!(eligible_on, Ok(eligible_on) if eligible_on <= current_block_number); - let is_known_good_judgment = reg.judgements.contains(&(0u32, KnownGood)); - is_citizen_field_set && is_eligible && is_known_good_judgment + is_eligible } - fn is_known_good(account: &T::AccountId) -> bool { - match pallet_identity::Pallet::::identity(account) { - Some(reg) => Self::is_known_good_identity(®), - None => false, - } + fn is_known_good( + reg: &pallet_identity::Registration< + BalanceOfIdentity, + T::MaxRegistrars, + T::MaxAdditionalFields, + >, + ) -> bool { + reg.judgements.contains(&(0u32, KnownGood)) + } + + fn is_dex_pool(account: &T::AccountId) -> bool { + pallet_asset_conversion::Pools::::iter_keys() + .map(|id| pallet_asset_conversion::Pallet::::get_pool_account(&id)) + .find(|addr| addr == account) + .is_some() } } impl CitizenshipChecker for Pallet { + fn ensure_stocks_allowed(account: &T::AccountId) -> Result<(), DispatchError> { + if Self::is_dex_pool(account) { + return Ok(()); + } + + let identity = + &pallet_identity::Pallet::::identity(account).ok_or(Error::::NonEResident)?; + let is_citizen_or_eresident = + Self::is_eresident_identity(identity) || Self::is_citizen_identity(identity); + ensure!(is_citizen_or_eresident, Error::::NonEResident); + ensure!(Self::is_known_good(identity), Error::::NonEResident); + ensure!(Self::is_eligible_identity(identity), Error::::NonEResident); + Ok(()) + } + fn ensure_politics_allowed(account: &T::AccountId) -> Result<(), DispatchError> { - ensure!(Self::is_known_good(account), Error::::NonCitizen); + let identity = + &pallet_identity::Pallet::::identity(account).ok_or(Error::::NonCitizen)?; + ensure!(Self::is_citizen_identity(identity), Error::::NonCitizen); + ensure!(Self::is_known_good(identity), Error::::NonCitizen); + ensure!(Self::is_eligible_identity(identity), Error::::NonCitizen); ensure!(Self::is_election_unlocked(account), Error::::Locked); ensure!(Self::check_pooled_llm(account), Error::::NoPolLLM); Ok(()) } fn ensure_validate_allowed(account: &T::AccountId) -> Result<(), DispatchError> { - ensure!(Self::is_known_good(account), Error::::NonCitizen); + let identity = + &pallet_identity::Pallet::::identity(account).ok_or(Error::::NonCitizen)?; + ensure!(Self::is_citizen_identity(identity), Error::::NonCitizen); + ensure!(Self::is_known_good(identity), Error::::NonCitizen); + ensure!(Self::is_eligible_identity(identity), Error::::NonCitizen); ensure!(Self::check_pooled_llm(account), Error::::NoPolLLM); Ok(()) } fn ensure_land_nfts_allowed(account: &T::AccountId) -> Result<(), DispatchError> { - ensure!(Self::is_known_good(account), Error::::NonCitizen); + let identity = + &pallet_identity::Pallet::::identity(account).ok_or(Error::::NonCitizen)?; + ensure!(Self::is_citizen_identity(identity), Error::::NonCitizen); + ensure!(Self::is_known_good(identity), Error::::NonCitizen); + ensure!(Self::is_eligible_identity(identity), Error::::NonCitizen); ensure!(Self::check_pooled_llm(account), Error::::NoPolLLM); Ok(()) } fn is_citizen(account: &T::AccountId) -> bool { - Self::is_known_good(account) + let identity = + pallet_identity::Pallet::::identity(account).ok_or(Error::::NonCitizen); + identity + .as_ref() + .map(|identity| { + Self::is_citizen_identity(identity) + && Self::is_known_good(identity) + && Self::is_eligible_identity(identity) + }) + .unwrap_or(false) } fn citizens_count() -> u64 { diff --git a/substrate/frame/llm/src/migrations.rs b/substrate/frame/llm/src/migrations.rs deleted file mode 100644 index 4238fc8886..0000000000 --- a/substrate/frame/llm/src/migrations.rs +++ /dev/null @@ -1,323 +0,0 @@ -use super::{pallet::Config, *}; -use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade}; -use frame_system::pallet_prelude::BlockNumberFor; -use liberland_traits::CitizenshipChecker; -use pallet_identity::Registration; -use sp_std::vec::Vec; - -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -pub mod v1 { - use super::*; - const TARGET: &'static str = "runtime::llm::migration::v1"; - - #[storage_alias] - pub type IdentityOf = StorageMap< - pallet_identity::Pallet, - Twox64Concat, - ::AccountId, - Registration< - BalanceOf, - ::MaxRegistrars, - ::MaxAdditionalFields, - >, - >; - - pub struct Migration(sp_std::marker::PhantomData); - - impl OnRuntimeUpgrade for Migration { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 0, "can only upgrade from version 0"); - - Ok(().encode()) - } - - fn on_runtime_upgrade() -> Weight { - let mut weight = T::DbWeight::get().reads(1); - if StorageVersion::get::>() != 0 { - log::warn!( - target: TARGET, - "skipping on_runtime_upgrade: executed on wrong storage version.\ - Expected version 0" - ); - return weight; - } - - IdentityOf::::translate( - |_, - reg: Registration< - BalanceOf, - ::MaxRegistrars, - ::MaxAdditionalFields, - >| { - let mut additional = Vec::new(); - let mut v = Vec::new(); - v.push(0); - additional.push(( - pallet_identity::Data::Raw(b"eligible_on".to_vec().try_into().unwrap()), - pallet_identity::Data::Raw(v.try_into().unwrap()), - )); - Some(pallet_identity::Registration { - info: pallet_identity::IdentityInfo { - additional: additional.try_into().unwrap(), - ..reg.info - }, - ..reg - }) - }, - ); - - let citizens_count = - IdentityOf::::iter_keys().filter(|id| Pallet::::is_citizen(id)).count(); - let citizens_count: u64 = citizens_count.try_into().unwrap(); - Citizens::::put(citizens_count); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - - StorageVersion::new(1).put::>(); - weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 1, "must upgrade"); - log::info!(target: TARGET, "Counted {} citizens", Citizens::::get(),); - Ok(()) - } - } -} - -pub mod ltm_to_lkn { - use super::*; - #[cfg(feature = "try-runtime")] - use sp_std::vec::Vec; - - const TARGET: &'static str = "runtime::llm::migration::ltm_to_lkn"; - - pub struct Migration(sp_std::marker::PhantomData); - - impl OnRuntimeUpgrade for Migration { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - Ok(().encode()) - } - - fn on_runtime_upgrade() -> Weight { - let weight = T::DbWeight::get().reads(1); - let origin = frame_system::RawOrigin::Root.into(); - - let id = ::AssetId::get(); - let name = T::AssetName::get(); - let symbol = T::AssetSymbol::get(); - - Assets::::force_set_metadata( - origin, - id.into(), - name.into(), - symbol.into(), - 12, - false, - ) - .unwrap(); - - log::warn!(target: TARGET, "Reset metadata of LLM asset!"); - - weight - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - Ok(()) - } - } -} - -pub mod v2 { - use super::*; - use pallet_identity::Data; - - const TARGET: &'static str = "runtime::llm::migration::v2"; - - #[storage_alias] - pub type IdentityOf = StorageMap< - pallet_identity::Pallet, - Twox64Concat, - ::AccountId, - Registration< - BalanceOf, - ::MaxRegistrars, - ::MaxAdditionalFields, - >, - >; - - /// Migration for adding origin type to proposals and referendums. - pub struct Migration(sp_std::marker::PhantomData); - - impl OnRuntimeUpgrade for Migration { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 1, "can only upgrade from version 1"); - Ok(().encode()) - } - - fn on_runtime_upgrade() -> Weight { - let weight = T::DbWeight::get().reads(1); - if StorageVersion::get::>() != 1 { - log::warn!( - target: TARGET, - "skipping on_runtime_upgrade: executed on wrong storage version.\ - Expected version 1" - ); - return weight; - } - - let mut translated = 0; - let mut skipped = 0; - let mut errored = 0; - IdentityOf::::translate( - |_, - reg: Registration< - BalanceOf, - ::MaxRegistrars, - ::MaxAdditionalFields, - >| { - let mut additional = reg.info.additional.clone(); - - // called twitter now, but this referred to citizen field in previous storage - // version - if reg.info.twitter != Data::None { - if let Err(_) = additional.try_push(( - Data::Raw(b"citizen".to_vec().try_into().unwrap()), - Data::Raw(b"1".to_vec().try_into().unwrap()), - )) { - errored += 1; - log::error!( - target: TARGET, - "Couldnt migrate Identity - exceeded MaxAdditionalFields!" - ); - } else { - translated += 1; - }; - } else { - skipped += 1; - } - - Some(pallet_identity::Registration { - info: pallet_identity::IdentityInfo { - additional: additional.try_into().unwrap(), - twitter: Data::None, // this was the citizen field - ..reg.info - }, - ..reg - }) - }, - ); - log::info!( - target: TARGET, - "Translated {} identities, skipped {}, errored on {}", - translated, - skipped, - errored - ); - - StorageVersion::new(2).put::>(); - weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 2, "must upgrade"); - Ok(()) - } - } -} - -pub mod v3 { - use super::*; - - const TARGET: &'static str = "runtime::llm::migration::v3"; - - pub struct Migration(sp_std::marker::PhantomData); - - impl OnRuntimeUpgrade for Migration { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - Ok(().encode()) - } - - fn on_runtime_upgrade() -> Weight { - let weight = T::DbWeight::get().reads(1); - if StorageVersion::get::>() > 2 { - log::warn!( - target: TARGET, - "skipping on_runtime_upgrade: executed on wrong storage version.\ - Expected version 2 or lower" - ); - return weight; - } - - let duration: BlockNumberFor = 432000u32.into(); - WithdrawlockDuration::::put(&duration); - ElectionlockDuration::::put(&duration); - - let _ = Withdrawlock::::clear(u32::MAX, None); - let _ = Electionlock::::clear(u32::MAX, None); - - StorageVersion::new(3).put::>(); - weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 3, "must upgrade"); - log::info!(target: TARGET, "WithdrawlockDuration set to {:?}, ElectionlockDuration set to {:?}", WithdrawlockDuration::::get(), ElectionlockDuration::::get(),); - Ok(()) - } - } -} - -pub mod v4 { - use super::*; - - const TARGET: &'static str = "runtime::llm::migration::v4"; - - pub struct Migration(sp_std::marker::PhantomData<(T, OldInterval)>); - - #[storage_alias] - type NextRelease = StorageValue, BlockNumberFor, ValueQuery>; - - impl>> OnRuntimeUpgrade - for Migration - { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - assert!(StorageVersion::get::>() == 3, "can only upgrade from version 3"); - - Ok(().encode()) - } - - fn on_runtime_upgrade() -> Weight { - let weight = T::DbWeight::get().reads(1); - if StorageVersion::get::>() != 3 { - log::warn!( - target: TARGET, - "skipping on_runtime_upgrade: executed on wrong storage version.\ - Expected version 3" - ); - return weight; - } - - LastRelease::::put(NextRelease::::get() - OldInterval::get()); - - StorageVersion::new(4).put::>(); - weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 4, "must upgrade"); - Ok(()) - } - } -} diff --git a/substrate/frame/llm/src/mock.rs b/substrate/frame/llm/src/mock.rs index d6bfaf214c..2f6cc3cd29 100644 --- a/substrate/frame/llm/src/mock.rs +++ b/substrate/frame/llm/src/mock.rs @@ -5,8 +5,10 @@ use frame_support::{ ord_parameter_types, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, EitherOfDiverse}, weights::Weight, + PalletId, }; use frame_system::{EnsureRoot, EnsureSigned, EnsureSignedBy}; +use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; use pallet_identity::{Data, IdentityInfo}; use sp_core::{ConstU16, H256}; use sp_runtime::{ @@ -24,8 +26,10 @@ frame_support::construct_runtime!( Assets: pallet_assets, Identity: pallet_identity, LLM: pallet_llm, + AssetConversion: pallet_asset_conversion, } ); + impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; type Balance = u64; @@ -47,6 +51,7 @@ impl pallet_assets::Config for Test { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = (); } parameter_types! { @@ -154,6 +159,39 @@ impl pallet_identity::Config for Test { type Citizenship = LLM; } +parameter_types! { + pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); + pub AllowMultiAssetPools: bool = true; + pub const PoolSetupFee: u64 = 1; + pub const MintMinLiquidity: u64 = 100; + pub const LiquidityWithdrawalFee: Permill = Permill::from_parts(0); +} + +impl pallet_asset_conversion::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type AssetBalance = ::Balance; + type HigherPrecisionBalance = u128; + type Assets = Assets; + type Balance = u64; + type PoolAssets = Assets; + type AssetId = ::AssetId; + type MultiAssetId = NativeOrAssetId; + type PoolAssetId = ::AssetId; + type PalletId = AssetConversionPalletId; + type LPFee = ConstU32<5>; // means 0.5%; + type PoolSetupFee = PoolSetupFee; + type PoolSetupFeeReceiver = (); + type LiquidityWithdrawalFee = LiquidityWithdrawalFee; + type WeightInfo = pallet_asset_conversion::weights::SubstrateWeight; + type AllowMultiAssetPools = AllowMultiAssetPools; + type MaxSwapPathLength = ConstU32<4>; + type MintMinLiquidity = MintMinLiquidity; + type MultiAssetIdConverter = NativeOrAssetIdConverter; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + pub fn setup_citizenships(accounts: Vec) { let data = Data::Raw(b"1".to_vec().try_into().unwrap()); let eligible_on = ( diff --git a/substrate/frame/staking/Cargo.toml b/substrate/frame/staking/Cargo.toml index e6d1917db3..1685ea7749 100644 --- a/substrate/frame/staking/Cargo.toml +++ b/substrate/frame/staking/Cargo.toml @@ -54,6 +54,7 @@ frame-benchmarking = { tag = "polkadot-v1.1.0", git = "https://github.com/parity frame-election-provider-support = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } rand_chacha = { version = "0.2" } pallet-nfts = { path = "../nfts" } +pallet-asset-conversion = { tag = "polkadot-v1.1.0", git = "https://github.com/paritytech/polkadot-sdk" } [features] default = [ "std" ] @@ -80,6 +81,7 @@ std = [ "pallet-identity/std", "pallet-llm/std", "pallet-liberland-initializer/std", + "pallet-asset-conversion/std", "liberland-traits/std", "sp-std/std", "sp-tracing/std", @@ -99,6 +101,7 @@ runtime-benchmarks = [ "pallet-liberland-initializer/runtime-benchmarks", "liberland-traits/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", ] try-runtime = [ "frame-election-provider-support/try-runtime", diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index 975a083f42..c59785f3bb 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -34,6 +34,7 @@ use frame_support::{ OnUnbalanced, OneSessionHandler, }, weights::constants::RocksDbWeight, + PalletId, }; use sp_core::H256; use sp_io; @@ -45,6 +46,7 @@ use sp_runtime::{ BuildStorage, }; use sp_staking::offence::{DisableStrategy, OffenceDetails, OnOffenceHandler}; +use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; pub const INIT_TIMESTAMP: u64 = 30_000; pub const BLOCK_TIME: u64 = 1000; @@ -109,6 +111,7 @@ frame_support::construct_runtime!( Identity: pallet_identity, LLM: pallet_llm, LiberlandInitializer: pallet_liberland_initializer, + AssetConversion: pallet_asset_conversion, } ); @@ -205,6 +208,39 @@ impl pallet_timestamp::Config for Test { type WeightInfo = (); } +parameter_types! { + pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon"); + pub AllowMultiAssetPools: bool = true; + pub const PoolSetupFee: u64 = 1; + pub const MintMinLiquidity: u64 = 100; + pub const LiquidityWithdrawalFee: Permill = Permill::from_parts(0); +} + +impl pallet_asset_conversion::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type AssetBalance = ::Balance; + type HigherPrecisionBalance = u128; + type Assets = Assets; + type Balance = u128; + type PoolAssets = Assets; + type AssetId = ::AssetId; + type MultiAssetId = NativeOrAssetId; + type PoolAssetId = ::AssetId; + type PalletId = AssetConversionPalletId; + type LPFee = ConstU32<5>; // means 0.5%; + type PoolSetupFee = PoolSetupFee; + type PoolSetupFeeReceiver = (); + type LiquidityWithdrawalFee = LiquidityWithdrawalFee; + type WeightInfo = pallet_asset_conversion::weights::SubstrateWeight; + type AllowMultiAssetPools = AllowMultiAssetPools; + type MaxSwapPathLength = ConstU32<4>; + type MintMinLiquidity = MintMinLiquidity; + type MultiAssetIdConverter = NativeOrAssetIdConverter; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + parameter_types! { pub const TOTALLLM: u64 = 70000000u64; pub const PRERELEASELLM: u64 = 7000000u64; @@ -321,6 +357,7 @@ impl pallet_assets::Config for Test { type RemoveItemsLimit = ConstU32<1000>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); + type Citizenship = (); } pallet_staking_reward_curve::build! {