Skip to content

Commit

Permalink
Merge branch 'featuire/pallet-communities-manager' of github.com:virt…
Browse files Browse the repository at this point in the history
…o-network/virto-node into featuire/pallet-communities-manager
  • Loading branch information
pandres95 committed Apr 21, 2024
2 parents 9cf16a0 + 7e46db5 commit 6c216df
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 151 deletions.
36 changes: 4 additions & 32 deletions pallets/communities-manager/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
//! Benchmarking setup for pallet-communities
#![cfg(feature = "runtime-benchmarks")]
use super::*;

use frame_benchmarking::v2::*;

use self::Pallet as CommunitiesManager;
use Pallet as CommunitiesManager;

use frame_system::RawOrigin;
use pallet_referenda::Curve;
use sp_runtime::{str_array as s, traits::StaticLookup, Perbill};
use sp_runtime::traits::StaticLookup;

type RuntimeEventFor<T> = <T as Config>::RuntimeEvent;

Expand Down Expand Up @@ -37,39 +34,14 @@ mod benchmarks {
_(
RawOrigin::Root,
community_id,
TrackInfo {
name: s("Test Track"),
max_deciding: 1,
decision_deposit: 0u32.into(),
prepare_period: 1u32.into(),
decision_period: 2u32.into(),
confirm_period: 1u32.into(),
min_enactment_period: 1u32.into(),
min_approval: pallet_referenda::Curve::LinearDecreasing {
length: Perbill::one(),
floor: Perbill::zero(),
ceil: Perbill::one(),
},
min_support: Curve::LinearDecreasing {
length: Perbill::one(),
floor: Perbill::zero(),
ceil: Perbill::one(),
},
},
BoundedVec::truncate_from(b"Test Community".into()),
Some(admin_origin_caller.clone()),
None,
Some(T::Lookup::unlookup(first_member)),
);

// verification code
assert_has_event::<T>(
pallet_communities::Event::<T>::CommunityCreated {
id: community_id,
origin: admin_origin_caller,
}
.into(),
);
assert_has_event::<T>(crate::Event::<T>::CommunityRegistered { id: community_id }.into());
assert_has_event::<T>(Event::<T>::CommunityRegistered { id: community_id }.into());
}

impl_benchmark_test_suite!(
Expand Down
58 changes: 42 additions & 16 deletions pallets/communities-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,19 @@ use pallet_communities::{
},
Origin as CommunityOrigin,
};
use pallet_nfts::{CollectionConfig, MintSettings, MintType::Issuer};
use pallet_nfts::CollectionConfig;
use pallet_referenda::{TrackInfo, TracksInfo};

type TrackInfoOf<T> = TrackInfo<NativeBalanceOf<T>, BlockNumberFor<T>>;

#[frame_support::pallet]
pub mod pallet {
use sp_runtime::str_array;

use super::*;

type CommunityName = BoundedVec<u8, ConstU32<25>>;

/// Configure the pallet by specifying the parameters and types on which it
/// depends.
#[pallet::config]
Expand Down Expand Up @@ -82,6 +86,8 @@ pub mod pallet {
// Errors inform users that something worked or went wrong.
#[pallet::error]
pub enum Error<T> {
/// Community name didn't contain valid utf8 characters
InvalidCommunityName,
/// It was not possible to register the community
CannotRegister,
}
Expand All @@ -96,16 +102,18 @@ pub mod pallet {
pub fn register(
origin: OriginFor<T>,
community_id: CommunityIdOf<T>,
track_info: TrackInfoOf<T>,
name: CommunityName,
maybe_admin_origin: Option<PalletsOriginOf<T>>,
maybe_decision_method: Option<DecisionMethodFor<T>>,
_maybe_first_member: Option<AccountIdLookupOf<T>>,
) -> DispatchResult {
let maybe_deposit = T::CreateOrigin::ensure_origin(origin)?;

// This implies depositing (Deposit (Hold | -> Treasury))
let community_name = core::str::from_utf8(&name).map_err(|_| Error::<T>::InvalidCommunityName)?;
let community_origin: RuntimeOriginFor<T> = CommunityOrigin::<T>::new(community_id).into();
let admin_origin = maybe_admin_origin.unwrap_or(community_origin.clone().into_caller());
// Register first to check if community exists
pallet_communities::Pallet::<T>::register(&admin_origin, &community_id, maybe_deposit)?;

if let Some(decision_method) = maybe_decision_method {
pallet_communities::Pallet::<T>::set_decision_method(
Expand All @@ -115,8 +123,6 @@ pub mod pallet {
)?;
}

pallet_communities::Pallet::<T>::register(&admin_origin, &community_id, maybe_deposit)?;

let community_account = pallet_communities::Pallet::<T>::community_account(&community_id);

// Create memberships collection for community
Expand All @@ -127,26 +133,46 @@ pub mod pallet {
&CollectionConfig {
settings: Default::default(),
max_supply: None,
mint_settings: MintSettings {
mint_type: Issuer,
price: None,
start_block: None,
end_block: None,
default_item_settings: Default::default(),
},
mint_settings: Default::default(),
},
)?;

// Create governance track for community
T::Tracks::insert(community_id, track_info, community_origin.into_caller())?;

T::Tracks::insert(
community_id,
Self::default_tack(community_name),
community_origin.into_caller(),
)?;
// Induct community at Kreivo Governance with rank 1
T::RankedCollective::induct(&community_account)?;
T::RankedCollective::promote(&community_account)?;

Self::deposit_event(Event::<T>::CommunityRegistered { id: community_id });

Ok(())
}
}

impl<T: Config> Pallet<T> {
fn default_tack(name: &str) -> TrackInfoOf<T> {
use sp_runtime::Perbill;
TrackInfo {
name: str_array(name),
max_deciding: 1,
decision_deposit: 0u8.into(),
prepare_period: 1u8.into(),
decision_period: u8::MAX.into(),
confirm_period: 1u8.into(),
min_enactment_period: 1u8.into(),
min_approval: pallet_referenda::Curve::LinearDecreasing {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(50),
ceil: Perbill::from_percent(100),
},
min_support: pallet_referenda::Curve::LinearDecreasing {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(0),
ceil: Perbill::from_percent(50),
},
}
}
}
}
25 changes: 8 additions & 17 deletions pallets/communities/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,19 @@ impl<T: Config> Pallet<T> {
Info::<T>::mutate(community_id, |c| c.as_mut().map(|c| c.state = state));
}

/// Stores an initial info about the community
/// Sets the caller as the community admin, the initial community state
/// to its default value(awaiting)
pub fn register(
admin: &PalletsOriginOf<T>,
community_id: &CommunityIdOf<T>,
maybe_deposit: Option<(NativeBalanceOf<T>, AccountIdOf<T>, AccountIdOf<T>)>,
) -> DispatchResult {
ensure!(
!Self::community_exists(community_id),
Error::<T>::CommunityAlreadyExists
);

if let Some((deposit, depositor, depositee)) = maybe_deposit {
T::Balances::transfer(
&depositor,
Expand All @@ -59,27 +67,10 @@ impl<T: Config> Pallet<T> {
)?;
}

Self::do_register_community(admin, community_id)
}

/// Stores an initial info about the community
/// Sets the caller as the community admin, the initial community state
/// to its default value(awaiting)
pub(crate) fn do_register_community(admin: &PalletsOriginOf<T>, community_id: &T::CommunityId) -> DispatchResult {
ensure!(
!Self::community_exists(community_id),
Error::<T>::CommunityAlreadyExists
);

CommunityIdFor::<T>::insert(admin, community_id);
Info::<T>::insert(community_id, CommunityInfo::default());
frame_system::Pallet::<T>::inc_providers(&Self::community_account(community_id));

Self::deposit_event(crate::Event::CommunityCreated {
id: *community_id,
origin: admin.clone(),
});

Ok(())
}

Expand Down
10 changes: 7 additions & 3 deletions pallets/communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ pub mod pallet {
let maybe_deposit = T::CreateOrigin::ensure_origin(origin)?;

Self::register(&admin_origin, &community_id, maybe_deposit)?;

Self::deposit_event(crate::Event::CommunityCreated {
id: community_id,
origin: admin_origin,
});
Ok(())
}

Expand Down Expand Up @@ -560,9 +565,8 @@ pub mod pallet {
let max_members = u16::MAX as u32;

if let Some((i, _)) = CommunityVotes::<T>::iter_keys().find(|(i, _)| T::Polls::as_ongoing(*i).is_none()) {
match CommunityVotes::<T>::clear_prefix(i, max_members, None) {
_ => Weight::zero(),
}
let _ = CommunityVotes::<T>::clear_prefix(i, max_members, None);
Weight::zero()
} else {
Weight::zero()
}
Expand Down
22 changes: 15 additions & 7 deletions pallets/communities/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ use frame_support::{
parameter_types,
traits::{
fungible::HoldConsideration, tokens::nonfungible_v2::ItemOf, AsEnsureOriginWithArg, ConstU128, ConstU16,
ConstU32, ConstU64, EitherOf, EnsureOriginWithArg, EqualPrivilegeOnly, Footprint, OriginTrait,
ConstU32, ConstU64, EitherOf, EnsureOriginWithArg, EqualPrivilegeOnly, Footprint,
},
weights::{
constants::{WEIGHT_REF_TIME_PER_NANOS, WEIGHT_REF_TIME_PER_SECOND},
Weight,
},
weights::{constants::WEIGHT_REF_TIME_PER_NANOS, constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
PalletId,
};
use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned};
Expand All @@ -21,7 +24,7 @@ pub use virto_common::{CommunityId, MembershipId};

use crate::{
self as pallet_communities,
origin::{DecisionMethod, EnsureCommunity, EnsureCreateOrigin},
origin::{DecisionMethod, EnsureCommunity, EnsureSignedPays},
types::{Tally, VoteWeight},
};

Expand Down Expand Up @@ -406,6 +409,12 @@ impl BenchmarkHelper<Test> for CommunityBenchmarkHelper {
}
}

parameter_types! {
pub const NoPay: Option<(Balance, AccountId, AccountId)> = None;
}
type RootCreatesCommunitiesForFree = EnsureRootWithSuccess<AccountId, NoPay>;
type AnyoneElsePays = EnsureSignedPays<Test, ConstU128<10>, RootAccount>;

impl pallet_communities::Config for Test {
type PalletId = CommunitiesPalletId;
type CommunityId = CommunityId;
Expand All @@ -416,8 +425,7 @@ impl pallet_communities::Config for Test {
type MemberMgmt = Nfts;
type Polls = Referenda;

type CreateOrigin =
EnsureCreateOrigin<Test, EnsureRoot<AccountId>, EnsureSigned<AccountId>, RootAccount, ConstU128<10>>;
type CreateOrigin = EitherOf<RootCreatesCommunitiesForFree, AnyoneElsePays>;
type AdminOrigin = EnsureCommunity<Self>;
type MemberMgmtOrigin = EnsureCommunity<Self>;

Expand Down Expand Up @@ -544,7 +552,7 @@ impl TestEnvBuilder {
.expect("should include decision_method on add_community");
let community_origin: RuntimeOrigin = Self::create_community_origin(community_id);

Communities::create(RuntimeOrigin::root(), community_origin.caller().clone(), *community_id)
Communities::create(RuntimeOrigin::root(), community_origin.caller.clone(), *community_id)
.expect("can add community");

Communities::set_decision_method(community_origin.clone(), *community_id, decision_method.clone())
Expand Down Expand Up @@ -575,7 +583,7 @@ impl TestEnvBuilder {
RuntimeOrigin::root(),
*community_id,
track_info.clone(),
community_origin.caller().clone(),
community_origin.caller.clone(),
)
.expect("can add track");
}
Expand Down
46 changes: 15 additions & 31 deletions pallets/communities/src/origin.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use crate::{
types::{CommunityIdOf, CommunityState::Active, MembershipIdOf, RuntimeOriginFor},
AccountIdOf, CommunityIdFor, Config, Info, NativeBalanceOf, Pallet,
AccountIdOf, CommunityIdFor, Config, Info, Pallet,
};
use core::marker::PhantomData;
use fc_traits_memberships::Inspect;
use frame_support::{
pallet_prelude::*,
traits::{membership::GenericRank, EnsureOriginWithArg, OriginTrait},
traits::{membership::GenericRank, EnsureOriginWithArg, MapSuccess, OriginTrait},
};
use frame_system::EnsureSigned;
#[cfg(feature = "xcm")]
use sp_runtime::traits::TryConvert;
use sp_runtime::Permill;
use sp_runtime::{morph_types, Permill};

pub struct EnsureCommunity<T>(PhantomData<T>);

Expand Down Expand Up @@ -45,36 +46,19 @@ where
}
}

pub struct EnsureCreateOrigin<T, R, P, D, A>(PhantomData<(T, R, P, D, A)>);

impl<OuterOrigin, T, Root, Permissionless, Destination, Amount> EnsureOrigin<OuterOrigin>
for EnsureCreateOrigin<T, Root, Permissionless, Destination, Amount>
where
OuterOrigin: From<frame_system::Origin<T>> + Clone,
T: Config,
Root: EnsureOrigin<OuterOrigin>,
Permissionless: EnsureOrigin<OuterOrigin, Success = AccountIdOf<T>>,
Destination: Get<AccountIdOf<T>>,
Amount: Get<NativeBalanceOf<T>>,
{
type Success = Option<(NativeBalanceOf<T>, AccountIdOf<T>, AccountIdOf<T>)>;

fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
match Root::try_origin(o.clone()) {
Ok(_) => Ok(None),
_ => match Permissionless::try_origin(o.clone()) {
Ok(sender) => Ok(Some((Amount::get(), sender, Destination::get()))),
_ => Err(o),
},
}
}

#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<OuterOrigin, ()> {
Ok(frame_system::Origin::<T>::Root.into())
}
morph_types! {
pub type PaymentForCreate<
AccountId,
GetAmount: TypedGet,
GetReceiver: TypedGet<Type = AccountId>
>: Morph = |sender: AccountId| -> Option<(GetAmount::Type, AccountId, GetReceiver::Type)> {
Some((GetAmount::get(), sender, GetReceiver::get()))
};
}

pub type EnsureSignedPays<T, Amount, Beneficiary> =
MapSuccess<EnsureSigned<AccountIdOf<T>>, PaymentForCreate<AccountIdOf<T>, Amount, Beneficiary>>;

pub struct EnsureMember<T>(PhantomData<T>);

impl<T> EnsureOriginWithArg<RuntimeOriginFor<T>, CommunityIdOf<T>> for EnsureMember<T>
Expand Down
1 change: 1 addition & 0 deletions runtime/kreivo/src/communities/governance.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;

use frame_system::{pallet_prelude::BlockNumberFor, EnsureRootWithSuccess};
use pallet_communities::RuntimeOriginFor;
use sp_std::marker::PhantomData;

use pallet_referenda::{BalanceOf, PalletsOriginOf, TrackIdOf, TracksInfo};
Expand Down
Loading

0 comments on commit 6c216df

Please sign in to comment.