Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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