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

introduce community treasuries MVP #401

Merged
merged 20 commits into from
Sep 10, 2024
Merged
61 changes: 58 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,32 @@ members = [
'rpc',
'scheduler',
'test-utils',
'treasuries',
'treasuries/rpc',
'treasuries/rpc/runtime-api',
'vouches',
]

[workspace.dependencies]
# local pin
encointer-ceremonies-assignment = { path = "ceremonies/assignment", default-features = false, version = "13.1.0" }
encointer-meetup-validation = { path = "ceremonies/meetup-validation", default-features = false, version = "13.1.0" }
encointer-primitives = { path = "primitives", default-features = false, features = ["serde_derive"], version = "13.1.0" }
encointer-primitives = { path = "primitives", default-features = false, features = ["serde_derive"], version = "13.3.0" }
encointer-rpc = { path = "rpc", version = "13.1.0" }
ep-core = { path = "primitives/core", default-features = false, version = "13.0.0" }
pallet-encointer-balances = { path = "balances", default-features = false, version = "13.1.0" }
pallet-encointer-ceremonies = { path = "ceremonies", default-features = false, version = "13.1.0" }
pallet-encointer-communities = { path = "communities", default-features = false, version = "13.1.0" }
pallet-encointer-reputation-commitments = { path = "reputation-commitments", default-features = false, version = "13.1.0" }
pallet-encointer-scheduler = { path = "scheduler", default-features = false, version = "13.1.0" }
pallet-encointer-treasuries = { path = "treasuries", default-features = false, version = "13.3.0" }
test-utils = { path = "test-utils" }
# rpc apis
encointer-balances-tx-payment-rpc-runtime-api = { path = "balances-tx-payment/rpc/runtime-api", version = "13.1.0" }
pallet-encointer-bazaar-rpc-runtime-api = { path = "bazaar/rpc/runtime-api", version = "13.1.0" }
pallet-encointer-ceremonies-rpc-runtime-api = { path = "ceremonies/rpc/runtime-api", version = "13.1.0" }
pallet-encointer-communities-rpc-runtime-api = { path = "communities/rpc/runtime-api", version = "13.1.0" }
pallet-encointer-treasuries-rpc-runtime-api = { path = "treasuries/rpc/runtime-api", version = "13.3.0" }

# various
array-bytes = "6.1.0"
Expand Down
3 changes: 2 additions & 1 deletion democracy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-encointer-democracy"
version = "13.2.0"
version = "13.3.0"
authors = ["Encointer Association <info@encointer.org>"]
edition = "2021"
description = "Democracy pallet for the Encointer blockchain runtime"
Expand All @@ -19,6 +19,7 @@ pallet-encointer-ceremonies = { workspace = true }
pallet-encointer-communities = { workspace = true }
pallet-encointer-reputation-commitments = { workspace = true }
pallet-encointer-scheduler = { workspace = true }
pallet-encointer-treasuries = { workspace = true }

# substrate deps
frame-support = { workspace = true }
Expand Down
6 changes: 5 additions & 1 deletion democracy/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ fn advance_timestamp_equivalent_to_n_blocks<T: Config>(n: u64) {
}

benchmarks! {

where_clause {
where
sp_core::H256: From<<T as frame_system::Config>::Hash>,
T::AccountId: AsRef<[u8; 32]>,
}
submit_proposal {
let zoran = account("zoran", 1, 1);
let cid = CommunityIdentifier::default();
Expand Down
43 changes: 34 additions & 9 deletions democracy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ extern crate alloc;
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::string::ToString;

use frame_support::traits::Currency;
// Logger target
//const LOG: &str = "encointer";

Expand All @@ -59,9 +59,13 @@ mod benchmarking;
pub use pallet::*;

type ReputationVecOf<T> = ReputationVec<<T as Config>::MaxReputationCount>;
pub type BalanceOf<T> = <<T as pallet_encointer_treasuries::Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::Balance;

use pallet_encointer_ceremonies::Pallet as CeremoniesPallet;
use pallet_encointer_communities::Pallet as CommunitiesPallet;
use pallet_encointer_treasuries::Pallet as TreasuriesPallet;

#[allow(clippy::unused_unit)]
#[frame_support::pallet]
Expand All @@ -88,6 +92,7 @@ pub mod pallet {
+ pallet_encointer_ceremonies::Config
+ pallet_encointer_communities::Config
+ pallet_encointer_reputation_commitments::Config
+ pallet_encointer_treasuries::Config
{
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

Expand Down Expand Up @@ -125,7 +130,7 @@ pub mod pallet {
},
ProposalSubmitted {
proposal_id: ProposalIdType,
proposal_action: ProposalAction,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>>,
},
VotePlaced {
proposal_id: ProposalIdType,
Expand Down Expand Up @@ -184,8 +189,13 @@ pub mod pallet {
/// All proposals that have ever been proposed including the past ones.
#[pallet::storage]
#[pallet::getter(fn proposals)]
pub(super) type Proposals<T: Config> =
StorageMap<_, Blake2_128Concat, ProposalIdType, Proposal<T::Moment>, OptionQuery>;
pub(super) type Proposals<T: Config> = StorageMap<
_,
Blake2_128Concat,
ProposalIdType,
Proposal<T::Moment, T::AccountId, BalanceOf<T>>,
OptionQuery,
>;

/// Proposal count of all proposals to date.
#[pallet::storage]
Expand Down Expand Up @@ -229,13 +239,17 @@ pub mod pallet {
}

#[pallet::call]
impl<T: Config> Pallet<T> {
impl<T: Config> Pallet<T>
where
sp_core::H256: From<<T as frame_system::Config>::Hash>,
T::AccountId: AsRef<[u8; 32]>,
{
#[pallet::call_index(0)]
#[pallet::weight((<T as Config>::WeightInfo::submit_proposal(), DispatchClass::Normal, Pays::Yes)
)]
pub fn submit_proposal(
origin: OriginFor<T>,
proposal_action: ProposalAction,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>>,
) -> DispatchResultWithPostInfo {
if Self::enactment_queue(proposal_action.clone().get_identifier()).is_some() {
return Err(Error::<T>::ProposalWaitingForEnactment.into());
Expand Down Expand Up @@ -330,7 +344,11 @@ pub mod pallet {
}
}

impl<T: Config> Pallet<T> {
impl<T: Config> Pallet<T>
where
sp_core::H256: From<<T as frame_system::Config>::Hash>,
T::AccountId: AsRef<[u8; 32]>,
{
/// Returns the cindexes eligible for voting on a proposal with `proposal_start`.
///
/// It is essentially the range of:
Expand Down Expand Up @@ -481,7 +499,7 @@ pub mod pallet {

pub fn get_electorate(
start_cindex: CeremonyIndexType,
proposal_action: ProposalAction,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>>,
) -> Result<ReputationCountType, Error<T>> {
let voting_cindexes = Self::voting_cindexes(start_cindex)?;

Expand Down Expand Up @@ -578,6 +596,9 @@ pub mod pallet {
text: petition.clone(),
});
},
ProposalAction::SpendNative(maybe_cid, ref beneficiary, amount) => {
TreasuriesPallet::<T>::do_spend_native(maybe_cid, beneficiary.clone(), amount)?;
},
};

proposal.state = ProposalState::Enacted;
Expand All @@ -588,7 +609,11 @@ pub mod pallet {
}
}

impl<T: Config> OnCeremonyPhaseChange for Pallet<T> {
impl<T: Config> OnCeremonyPhaseChange for Pallet<T>
where
sp_core::H256: From<<T as frame_system::Config>::Hash>,
T::AccountId: AsRef<[u8; 32]>,
{
fn on_ceremony_phase_change(new_phase: CeremonyPhaseType) {
match new_phase {
CeremonyPhaseType::Assigning => {
Expand Down
4 changes: 4 additions & 0 deletions democracy/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ frame_support::construct_runtime!(
{
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
EncointerScheduler: pallet_encointer_scheduler::{Pallet, Call, Storage, Config<T>, Event},
EncointerCommunities: pallet_encointer_communities::{Pallet, Call, Storage, Event<T>},
EncointerCeremonies: pallet_encointer_ceremonies::{Pallet, Call, Storage, Event<T>},
EncointerBalances: pallet_encointer_balances::{Pallet, Call, Storage, Event<T>},
EncointerDemocracy: dut::{Pallet, Call, Storage, Config<T>, Event<T>},
EncointerReputationCommitments:pallet_encointer_reputation_commitments::{Pallet, Call, Storage, Event<T>},
EncointerTreasuries: pallet_encointer_treasuries::{Pallet, Event<T>},
}
);

Expand All @@ -56,11 +58,13 @@ impl dut::Config for TestRuntime {
// boilerplate
impl_frame_system!(TestRuntime);
impl_timestamp!(TestRuntime, EncointerScheduler);
impl_balances!(TestRuntime, System);
impl_encointer_balances!(TestRuntime);
impl_encointer_communities!(TestRuntime);
impl_encointer_scheduler!(TestRuntime, EncointerDemocracy);
impl_encointer_ceremonies!(TestRuntime);
impl_encointer_reputation_commitments!(TestRuntime);
impl_encointer_treasuries!(TestRuntime);

// genesis values
pub fn new_test_ext() -> sp_io::TestExternalities {
Expand Down
41 changes: 37 additions & 4 deletions democracy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

use super::*;
use crate::mock::{
EncointerBalances, EncointerCeremonies, EncointerCommunities, EncointerScheduler, Timestamp,
Balances, EncointerBalances, EncointerCeremonies, EncointerCommunities, EncointerScheduler,
EncointerTreasuries, Timestamp,
};
use encointer_primitives::{
balances::Demurrage,
Expand Down Expand Up @@ -408,7 +409,7 @@ fn do_update_proposal_state_fails_with_inexistent_proposal() {
fn do_update_proposal_state_fails_with_wrong_state() {
new_test_ext().execute_with(|| {
let cid = create_cid();
let proposal: Proposal<Moment> = Proposal {
let proposal: Proposal<Moment, AccountId, Balance> = Proposal {
start: Moment::from(1u64),
start_cindex: 1,
action: ProposalAction::UpdateNominalIncome(cid, NominalIncomeType::from(100u32)),
Expand All @@ -417,7 +418,7 @@ fn do_update_proposal_state_fails_with_wrong_state() {
};
Proposals::<TestRuntime>::insert(1, proposal);

let proposal2: Proposal<Moment> = Proposal {
let proposal2: Proposal<Moment, AccountId, Balance> = Proposal {
start: Moment::from(1u64),
start_cindex: 1,
action: ProposalAction::UpdateNominalIncome(cid, NominalIncomeType::from(100u32)),
Expand All @@ -426,7 +427,7 @@ fn do_update_proposal_state_fails_with_wrong_state() {
};
Proposals::<TestRuntime>::insert(2, proposal2);

let proposal3: Proposal<Moment> = Proposal {
let proposal3: Proposal<Moment, AccountId, Balance> = Proposal {
start: Moment::from(1u64),
start_cindex: 1,
action: ProposalAction::UpdateNominalIncome(cid, NominalIncomeType::from(100u32)),
Expand Down Expand Up @@ -1024,6 +1025,38 @@ fn enact_petition_works() {
});
}

#[test]
fn enact_spend_native_works() {
new_test_ext().execute_with(|| {
System::set_block_number(System::block_number() + 1); // this is needed to assert events
let beneficiary = AccountId::from(AccountKeyring::Alice);
let amount: BalanceOf<TestRuntime> = 100_000_000;
let cid = CommunityIdentifier::default();

let treasury = EncointerTreasuries::get_community_treasury_account_unchecked(Some(cid));
Balances::make_free_balance_be(&treasury, 500_000_000);

let alice = alice();
let proposal_action = ProposalAction::SpendNative(Some(cid), beneficiary.clone(), amount);
assert_ok!(EncointerDemocracy::submit_proposal(
RuntimeOrigin::signed(alice.clone()),
proposal_action.clone()
));

// directly inject the proposal into the enactment queue
EnactmentQueue::<TestRuntime>::insert(proposal_action.clone().get_identifier(), 1);

run_to_next_phase();
// first assigning phase after proposal lifetime ended

assert_eq!(EncointerDemocracy::proposals(1).unwrap().state, ProposalState::Enacted);
assert_eq!(EncointerDemocracy::enactment_queue(proposal_action.get_identifier()), None);

assert_eq!(Balances::free_balance(&treasury), 400_000_000);
assert_eq!(Balances::free_balance(&beneficiary), amount);
});
}

#[test]
fn enactment_error_fires_event() {
new_test_ext().execute_with(|| {
Expand Down
2 changes: 1 addition & 1 deletion primitives/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "encointer-primitives"
version = "13.2.0"
version = "13.3.0"
authors = ["Encointer Association <info@encointer.org>"]
edition = "2021"
description = "Primitives for the Encointer blockchain runtime"
Expand Down
Loading
Loading