Skip to content

Commit

Permalink
Automatically create the asset of a community if it doesnt exist yet (#…
Browse files Browse the repository at this point in the history
…399)

* Automatically create the asset of a community if it doesnt exist yet

* change(pallet-communities): solve testing issues

---------

Co-authored-by: Pablo Andrés Dorado Suárez <[email protected]>
  • Loading branch information
olanod and pandres95 authored May 14, 2024
1 parent 810c49d commit 9d0511d
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 56 deletions.
12 changes: 4 additions & 8 deletions pallets/communities/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
use super::*;

use self::{
origin::DecisionMethod,
types::{
AccountIdOf, AssetIdOf, CommunityIdOf, DecisionMethodFor, MembershipIdOf, NativeBalanceOf, PalletsOriginOf,
PollIndexOf, RuntimeCallFor, Vote,
},
CommunityDecisionMethod, Event, HoldReason, Pallet as Communities,
CommunityDecisionMethod, DecisionMethod, Event, HoldReason, Pallet as Communities,
};
use fc_traits_memberships::{Inspect, Rank};
use frame_benchmarking::v2::*;
use frame_support::traits::{
fungible::{InspectFreeze, Mutate},
fungibles::{Create, Mutate as FunsMutate},
fungibles::Mutate as FunsMutate,
OriginTrait,
};
use frame_system::{
Expand Down Expand Up @@ -197,7 +196,7 @@ mod benchmarks {
_(
admin_origin,
id,
DecisionMethod::CommunityAsset(T::BenchmarkHelper::community_asset_id()),
DecisionMethod::CommunityAsset(T::BenchmarkHelper::community_asset_id(), 10u128.into()),
);

// verification code
Expand Down Expand Up @@ -316,7 +315,7 @@ mod benchmarks {
// setup code
let (id, origin) = create_community::<T>(
RawOrigin::Root.into(),
Some(DecisionMethodFor::<T>::CommunityAsset(1u32.into())),
Some(DecisionMethodFor::<T>::CommunityAsset(1u32.into(), 1u128.into())),
)?;
let members = setup_members::<T>(origin.clone(), id)?;

Expand All @@ -325,9 +324,6 @@ mod benchmarks {
.expect("desired size of community to be equal or greather than 1")
.clone();

let community_account = Communities::<T>::community_account(&id);

T::Assets::create(1u32.into(), community_account, false, 1u128.into())?;
T::Assets::mint_into(1u32.into(), &who, 4u128.into())?;

prepare_track_and_prepare_poll::<T>(origin.into_caller(), who.clone())?;
Expand Down
7 changes: 5 additions & 2 deletions pallets/communities/src/functions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{origin::DecisionMethod, *};
use super::*;
use fc_traits_memberships::{GenericRank, Inspect, Rank};
use frame_support::{
dispatch::PostDispatchInfo,
Expand Down Expand Up @@ -95,7 +95,10 @@ impl<T: Config> Pallet<T> {
};

let say = *match (vote, decision_method) {
(Vote::AssetBalance(say, asset, ..), DecisionMethod::CommunityAsset(a)) if asset == a => say,
(Vote::AssetBalance(say, asset, amount), DecisionMethod::CommunityAsset(a, min)) if asset == a => {
ensure!(amount >= min, Error::<T>::VoteBelowMinimum);
say
}
(Vote::NativeBalance(say, ..), DecisionMethod::NativeToken)
| (Vote::Standard(say), DecisionMethod::Membership | DecisionMethod::Rank) => say,
_ => fail!(Error::<T>::InvalidVoteType),
Expand Down
21 changes: 15 additions & 6 deletions pallets/communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,8 @@ pub mod pallet {
Blake2_128Concat, Parameter,
};
use frame_system::pallet_prelude::{ensure_signed, BlockNumberFor, OriginFor};
use sp_runtime::{
traits::{Dispatchable, StaticLookup},
TokenError,
};
use sp_runtime::traits::AccountIdConversion;
use sp_runtime::traits::{Dispatchable, StaticLookup};
use sp_std::prelude::Box;

const ONE: NonZeroU8 = NonZeroU8::MIN;
Expand Down Expand Up @@ -193,7 +191,7 @@ pub mod pallet {
>;

/// Type represents interactions between fungibles (i.e. assets)
type Assets: fungibles::Inspect<Self::AccountId>
type Assets: fungibles::Inspect<Self::AccountId, Balance = NativeBalanceOf<Self>>
+ fungibles::Mutate<Self::AccountId>
+ fungibles::Create<Self::AccountId>
+ fungibles::hold::Inspect<Self::AccountId, Reason = Self::RuntimeHoldReason>
Expand Down Expand Up @@ -351,6 +349,8 @@ pub mod pallet {
NoLocksInPlace,
/// The origin already controls another community
AlreadyAdmin,
/// The vote is below the minimum requried
VoteBelowMinimum,
}

// Dispatchable functions allows users to interact with the pallet and invoke
Expand Down Expand Up @@ -477,6 +477,15 @@ pub mod pallet {
decision_method: DecisionMethodFor<T>,
) -> DispatchResult {
T::AdminOrigin::ensure_origin(origin)?;
if let DecisionMethod::CommunityAsset(ref asset, min_vote) = decision_method {
// best effort attemt to create the asset if it doesn't exist
let _ = <T::Assets as fungibles::Create<T::AccountId>>::create(
asset.clone(),
T::PalletId::get().into_account_truncating(),
false,
min_vote,
);
}
CommunityDecisionMethod::<T>::set(community_id, decision_method);
Self::deposit_event(Event::DecisionMethodSet { id: community_id });
Ok(())
Expand All @@ -490,7 +499,7 @@ pub mod pallet {
#[pallet::compact] poll_index: PollIndexOf<T>,
vote: VoteOf<T>,
) -> DispatchResult {
ensure!(VoteWeight::from(&vote).gt(&0), TokenError::BelowMinimum);
ensure!(VoteWeight::from(&vote).gt(&0), Error::<T>::VoteBelowMinimum);
let who = ensure_signed(origin)?;
let community_id = T::MemberMgmt::check_membership(&who, &membership_id).ok_or(Error::<T>::NotAMember)?;
let decision_method = CommunityDecisionMethod::<T>::get(community_id);
Expand Down
7 changes: 4 additions & 3 deletions pallets/communities/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ pub use virto_common::{CommunityId, MembershipId};

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

// Weights constants
Expand Down Expand Up @@ -455,7 +456,7 @@ pub(crate) struct TestEnvBuilder {
assets_config: AssetsConfig,
balances: Vec<(AccountId, Balance)>,
communities: Vec<CommunityId>,
decision_methods: sp_std::collections::btree_map::BTreeMap<CommunityId, DecisionMethod<AssetId>>,
decision_methods: sp_std::collections::btree_map::BTreeMap<CommunityId, DecisionMethod<AssetId, Balance>>,
members: Vec<(CommunityId, AccountId)>,
memberships: Vec<(CommunityId, MembershipId)>,
tracks: Vec<(TrackIdOf<Test, ()>, TrackInfoOf<Test>)>,
Expand Down Expand Up @@ -498,7 +499,7 @@ impl TestEnvBuilder {
pub(crate) fn add_community(
mut self,
community_id: CommunityId,
decision_method: DecisionMethod<AssetId>,
decision_method: DecisionMethod<AssetId, Balance>,
members: &[AccountId],
memberships: &[MembershipId],
maybe_track: Option<TrackInfoOf<Test>>,
Expand Down
10 changes: 0 additions & 10 deletions pallets/communities/src/origin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,6 @@ pub enum Subset<T: Config> {
AtLeastRank(GenericRank),
}

/// The mechanism used by the community or one of its subsets to make decisions
#[derive(Clone, Debug, Decode, Default, Encode, Eq, MaxEncodedLen, PartialEq, TypeInfo)]
pub enum DecisionMethod<AssetId> {
#[default]
Membership,
NativeToken,
CommunityAsset(AssetId),
Rank,
}

#[cfg(feature = "xcm")]
impl<T> TryConvert<RuntimeOriginFor<T>, xcm::v3::MultiLocation> for RawOrigin<T>
where
Expand Down
68 changes: 44 additions & 24 deletions pallets/communities/src/tests/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use parity_scale_codec::Encode;
use sp_runtime::{str_array as s, BoundedVec, TokenError};

use crate::{
origin::DecisionMethod,
types::{Tally, Vote},
Call,
Call, DecisionMethod,
};
use frame_support::assert_noop;
use pallet_referenda::TrackInfo;
Expand Down Expand Up @@ -108,7 +107,7 @@ fn new_test_ext() -> sp_io::TestExternalities {
// Community-asset based
.add_community(
COMMUNITY_B,
DecisionMethod::CommunityAsset(COMMUNITY_B_ASSET_ID),
DecisionMethod::CommunityAsset(COMMUNITY_B_ASSET_ID, 10),
&[BOB, CHARLIE],
memberships_of(COMMUNITY_B),
Some(CommunityTrack::get()),
Expand All @@ -119,7 +118,7 @@ fn new_test_ext() -> sp_io::TestExternalities {
true,
1,
None,
Some(vec![(BOB, 10), (CHARLIE, 10)]),
Some(vec![(BOB, 50), (CHARLIE, 50)]),
)
// Native-asset based
.add_community(
Expand Down Expand Up @@ -210,7 +209,7 @@ mod vote {
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 0)
),
TokenError::BelowMinimum
Error::VoteBelowMinimum
);
});
}
Expand Down Expand Up @@ -537,13 +536,34 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 10)
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 50)
),
TokenError::FundsUnavailable
);
});
}

#[test]
fn fails_if_asset_vote_weight_is_under_minimum() {
new_test_ext().execute_with(|| {
assert_noop!(
Communities::vote(
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 9)
),
Error::VoteBelowMinimum
);
assert_ok!(Communities::vote(
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 10)
));
});
}

#[test]
fn holds_cannot_overlap() {
new_test_ext().execute_with(|| {
Expand All @@ -552,7 +572,7 @@ mod vote {
COMMUNITY_B_ASSET_ID,
&pallet_preimage::HoldReason::Preimage.into(),
&CHARLIE,
6,
40,
));

// Before voting, the poll is ongoing
Expand All @@ -561,7 +581,7 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 5)
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 15)
),
TokenError::FundsUnavailable
);
Expand Down Expand Up @@ -589,7 +609,7 @@ mod vote {
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 6)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 30)
));

tick_block();
Expand All @@ -598,7 +618,7 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 6)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 30)
));

tick_block();
Expand All @@ -611,9 +631,9 @@ mod vote {
pallet_referenda::Event::<Test>::Confirmed {
index: 1,
tally: Tally {
ayes: 12,
ayes: 60,
nays: 0,
bare_ayes: 12,
bare_ayes: 60,
..Default::default()
},
}
Expand Down Expand Up @@ -643,7 +663,7 @@ mod vote {
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 2)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 12)
));

tick_block();
Expand All @@ -652,7 +672,7 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 1)
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 11)
));

tick_blocks(4);
Expand All @@ -665,9 +685,9 @@ mod vote {
pallet_referenda::Event::<Test>::Confirmed {
index: 1,
tally: Tally {
ayes: 2,
nays: 1,
bare_ayes: 2,
ayes: 12,
nays: 11,
bare_ayes: 12,
..Default::default()
},
}
Expand Down Expand Up @@ -699,7 +719,7 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 6)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 11)
));

tick_block();
Expand All @@ -708,7 +728,7 @@ mod vote {
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 7)
Vote::AssetBalance(false, COMMUNITY_B_ASSET_ID, 12)
));

tick_block();
Expand All @@ -717,7 +737,7 @@ mod vote {
RuntimeOrigin::signed(CHARLIE),
membership(COMMUNITY_B, 2),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 8)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 13)
));

tick_blocks(3);
Expand All @@ -726,9 +746,9 @@ mod vote {
pallet_referenda::Event::<Test>::Confirmed {
index: 1,
tally: Tally {
ayes: 8,
nays: 7,
bare_ayes: 8,
ayes: 13,
nays: 12,
bare_ayes: 13,
..Default::default()
},
}
Expand Down Expand Up @@ -1156,7 +1176,7 @@ mod unlock {
RuntimeOrigin::signed(BOB),
membership(COMMUNITY_B, 1),
1,
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 9)
Vote::AssetBalance(true, COMMUNITY_B_ASSET_ID, 15)
));

assert_ok!(Communities::vote(
Expand Down
Loading

0 comments on commit 9d0511d

Please sign in to comment.