Skip to content

Commit

Permalink
swap_native options proposals (#411)
Browse files Browse the repository at this point in the history
* fix permill->perthousand

* fmt

* initial implementation of swap options

* add unit tests

* consisten names

* clippy

* bump crate versions

* bump crate versions

* bump crate versions

* fix obsolete traitbounds (#413)

* bump toolchain

* add benchmarks for treasuries

---------

Co-authored-by: clangenb <[email protected]>
  • Loading branch information
brenzi and clangenb authored Jan 14, 2025
1 parent 919520a commit dcc5c9b
Show file tree
Hide file tree
Showing 19 changed files with 551 additions and 51 deletions.
11 changes: 7 additions & 4 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ members = [
# local pin
encointer-ceremonies-assignment = { path = "ceremonies/assignment", default-features = false, version = "14.1.0" }
encointer-meetup-validation = { path = "ceremonies/meetup-validation", default-features = false, version = "14.1.0" }
encointer-primitives = { path = "primitives", default-features = false, features = ["serde_derive"], version = "14.3.0" }
encointer-primitives = { path = "primitives", default-features = false, features = ["serde_derive"], version = "14.4.0" }
encointer-rpc = { path = "rpc", version = "14.1.0" }
ep-core = { path = "primitives/core", default-features = false, version = "14.0.0" }
pallet-encointer-balances = { path = "balances", default-features = false, version = "14.1.0" }
pallet-encointer-balances = { path = "balances", default-features = false, version = "14.2.0" }
pallet-encointer-ceremonies = { path = "ceremonies", default-features = false, version = "14.1.0" }
pallet-encointer-communities = { path = "communities", default-features = false, version = "14.1.0" }
pallet-encointer-reputation-commitments = { path = "reputation-commitments", default-features = false, version = "14.1.0" }
pallet-encointer-scheduler = { path = "scheduler", default-features = false, version = "14.1.0" }
pallet-encointer-treasuries = { path = "treasuries", default-features = false, version = "14.3.0" }
pallet-encointer-treasuries = { path = "treasuries", default-features = false, version = "14.4.0" }
test-utils = { path = "test-utils" }
# rpc apis
encointer-balances-tx-payment-rpc-runtime-api = { path = "balances-tx-payment/rpc/runtime-api", version = "14.1.0" }
Expand Down
2 changes: 1 addition & 1 deletion balances/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-encointer-balances"
version = "14.1.0"
version = "14.2.0"
authors = ["Encointer Association <[email protected]>"]
edition = "2021"
description = "Balances pallet for the Encointer blockchain runtime"
Expand Down
39 changes: 21 additions & 18 deletions balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub mod pallet {
amount: BalanceType,
) -> DispatchResultWithPostInfo {
let from = ensure_signed(origin)?;
Self::do_transfer(community_id, from, dest, amount)?;
Self::do_transfer(community_id, &from, &dest, amount)?;
Ok(().into())
}

Expand All @@ -122,7 +122,7 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
let from = ensure_signed(origin)?;
let amount = Self::balance(cid, &from);
Self::do_transfer(cid, from, dest, amount)?;
Self::do_transfer(cid, &from, &dest, amount)?;
Ok(().into())
}
}
Expand All @@ -134,8 +134,8 @@ pub mod pallet {
///
/// [CC]: 1 Unit of Community Currency
/// NI: Nominal Income. Unit = [CC]
/// FCF: Fee Conversion Factor. Unit = [1/ KKSM] <- Kilo-KSM to be able to adjust fee factor
/// in both ways. CB: Balance in Community Currency [CC]
/// FCF: Fee Conversion Factor. Unit = [1/ KKSM] <- Kilo-KSM to be able to adjust fee
/// factor in both ways. CB: Balance in Community Currency [CC]
///
/// The following equation should hold for fee design:
/// KSM * FCF * NI = CB -> FCF = CB / (NI * KSM)
Expand Down Expand Up @@ -164,6 +164,8 @@ pub mod pallet {
Transferred(CommunityIdentifier, T::AccountId, T::AccountId, BalanceType),
/// Token issuance success `[community_id, beneficiary, amount]`
Issued(CommunityIdentifier, T::AccountId, BalanceType),
/// Token burn success `[community_id, who, amount]`
Burned(CommunityIdentifier, T::AccountId, BalanceType),
/// fee conversion factor updated successfully
FeeConversionFactorUpdated(FeeConversionFactorType),
}
Expand Down Expand Up @@ -272,47 +274,47 @@ impl<T: Config> Pallet<T> {

pub fn do_transfer(
cid: CommunityIdentifier,
source: T::AccountId,
dest: T::AccountId,
source: &T::AccountId,
dest: &T::AccountId,
amount: BalanceType,
) -> Result<BalanceType, DispatchError> {
// Early exist if no-op.
if amount == 0u128 {
Self::deposit_event(Event::Transferred(cid, source, dest, amount));
Self::deposit_event(Event::Transferred(cid, source.clone(), dest.clone(), amount));
return Ok(amount);
}

ensure!(Balance::<T>::contains_key(cid, &source), Error::<T>::NoAccount);
ensure!(Balance::<T>::contains_key(cid, source), Error::<T>::NoAccount);

let mut entry_from = Self::balance_entry_updated(cid, &source);
let mut entry_from = Self::balance_entry_updated(cid, source);

ensure!(entry_from.principal >= amount, Error::<T>::BalanceTooLow);

if source == dest {
<Balance<T>>::insert(cid, &source, entry_from);
<Balance<T>>::insert(cid, source, entry_from);
return Ok(amount);
}

if !Balance::<T>::contains_key(cid, &dest) {
if !Balance::<T>::contains_key(cid, dest) {
ensure!(amount > T::ExistentialDeposit::get(), Error::<T>::ExistentialDeposit);
Self::new_account(&dest)?;
Self::new_account(dest)?;
Self::deposit_event(Event::Endowed { cid, who: dest.clone(), balance: amount });
}

let mut entry_to = Self::balance_entry_updated(cid, &dest);
let mut entry_to = Self::balance_entry_updated(cid, dest);

entry_from.principal = entry_from.principal.saturating_sub(amount);
entry_to.principal = entry_to.principal.saturating_add(amount);

<Balance<T>>::insert(cid, &source, entry_from);
<Balance<T>>::insert(cid, &dest, entry_to);
<Balance<T>>::insert(cid, source, entry_from);
<Balance<T>>::insert(cid, dest, entry_to);

Self::deposit_event(Event::Transferred(cid, source.clone(), dest, amount));
Self::deposit_event(Event::Transferred(cid, source.clone(), dest.clone(), amount));

// remove account if it falls beloe existential deposit
entry_from = Self::balance_entry_updated(cid, &source);
entry_from = Self::balance_entry_updated(cid, source);
if entry_from.principal < T::ExistentialDeposit::get() {
Self::remove_account(cid, &source)?;
Self::remove_account(cid, source)?;
}

Ok(amount)
Expand Down Expand Up @@ -360,6 +362,7 @@ impl<T: Config> Pallet<T> {

<TotalIssuance<T>>::insert(community_id, entry_tot);
<Balance<T>>::insert(community_id, who, entry_who);
Self::deposit_event(Event::Burned(community_id, who.clone(), amount));
Ok(())
}

Expand Down
2 changes: 1 addition & 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 = "14.3.2"
version = "14.4.0"
authors = ["Encointer Association <[email protected]>"]
edition = "2021"
description = "Democracy pallet for the Encointer blockchain runtime"
Expand Down
11 changes: 7 additions & 4 deletions democracy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub mod pallet {
},
ProposalSubmitted {
proposal_id: ProposalIdType,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>>,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>, T::Moment>,
},
VotePlaced {
proposal_id: ProposalIdType,
Expand Down Expand Up @@ -247,7 +247,7 @@ pub mod pallet {
)]
pub fn submit_proposal(
origin: OriginFor<T>,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>>,
proposal_action: ProposalAction<T::AccountId, BalanceOf<T>, T::Moment>,
) -> DispatchResultWithPostInfo {
if Self::enactment_queue(proposal_action.clone().get_identifier()).is_some() {
return Err(Error::<T>::ProposalWaitingForEnactment.into());
Expand Down Expand Up @@ -497,7 +497,7 @@ pub mod pallet {

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

Expand Down Expand Up @@ -595,7 +595,10 @@ pub mod pallet {
});
},
ProposalAction::SpendNative(maybe_cid, ref beneficiary, amount) => {
TreasuriesPallet::<T>::do_spend_native(maybe_cid, beneficiary.clone(), amount)?;
TreasuriesPallet::<T>::do_spend_native(maybe_cid, beneficiary, amount)?;
},
ProposalAction::IssueSwapNativeOption(cid, ref owner, swap_option) => {
TreasuriesPallet::<T>::do_issue_swap_native_option(cid, owner, swap_option)?;
},
};

Expand Down
39 changes: 38 additions & 1 deletion democracy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ use crate::mock::{
EncointerTreasuries, Timestamp,
};
use encointer_primitives::{
balances::Demurrage,
balances::{BalanceType, Demurrage},
ceremonies::{InactivityTimeoutType, Reputation},
common::{FromStr, PalletString},
communities::{
CommunityIdentifier, CommunityMetadata as CommunityMetadataType, Degree, GeoHash, Location,
NominalIncome as NominalIncomeType,
},
democracy::{ProposalAction, ProposalActionIdentifier, ProposalState, Tally, Vote},
treasuries::SwapNativeOption,
};
use frame_support::{
assert_err, assert_ok,
Expand Down Expand Up @@ -1056,7 +1057,43 @@ fn enact_spend_native_works() {
assert_eq!(Balances::free_balance(&beneficiary), amount);
});
}
#[test]
fn enact_issue_swap_native_option_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 native_allowance: BalanceOf<TestRuntime> = 100_000_000;
let rate = Some(BalanceType::from_num(1.5));
let cid = CommunityIdentifier::default();
let swap_option: SwapNativeOption<Balance, Moment> = SwapNativeOption {
cid,
native_allowance,
rate,
do_burn: true,
valid_from: None,
valid_until: None,
};

let alice = alice();
let proposal_action =
ProposalAction::IssueSwapNativeOption(cid, beneficiary.clone(), swap_option);
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!(EncointerTreasuries::swap_native_options(cid, beneficiary), Some(swap_option));
});
}
#[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 = "14.3.0"
version = "14.4.0"
authors = ["Encointer Association <[email protected]>"]
edition = "2021"
description = "Primitives for the Encointer blockchain runtime"
Expand Down
17 changes: 13 additions & 4 deletions primitives/src/democracy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use crate::{
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

use crate::{ceremonies::ReputationCountType, common::PalletString, scheduler::CeremonyIndexType};
use crate::{
ceremonies::ReputationCountType, common::PalletString, scheduler::CeremonyIndexType,
treasuries::SwapNativeOption,
};
#[cfg(feature = "serde_derive")]
use serde::{Deserialize, Serialize};
use sp_core::RuntimeDebug;
Expand Down Expand Up @@ -49,7 +52,7 @@ pub enum ProposalAccessPolicy {
#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde_derive", serde(rename_all = "camelCase"))]
pub enum ProposalAction<AccountId, Balance> {
pub enum ProposalAction<AccountId, Balance, Moment> {
AddLocation(CommunityIdentifier, Location),
RemoveLocation(CommunityIdentifier, Location),
UpdateCommunityMetadata(CommunityIdentifier, CommunityMetadataType),
Expand All @@ -58,6 +61,7 @@ pub enum ProposalAction<AccountId, Balance> {
SetInactivityTimeout(InactivityTimeoutType),
Petition(Option<CommunityIdentifier>, PalletString),
SpendNative(Option<CommunityIdentifier>, AccountId, Balance),
IssueSwapNativeOption(CommunityIdentifier, AccountId, SwapNativeOption<Balance, Moment>),
}

#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
Expand All @@ -72,9 +76,10 @@ pub enum ProposalActionIdentifier {
SetInactivityTimeout,
Petition(Option<CommunityIdentifier>),
SpendNative(Option<CommunityIdentifier>),
IssueSwapNativeOption(CommunityIdentifier),
}

impl<AccountId, Balance> ProposalAction<AccountId, Balance> {
impl<AccountId, Balance, Moment> ProposalAction<AccountId, Balance, Moment> {
pub fn get_access_policy(&self) -> ProposalAccessPolicy {
match self {
ProposalAction::AddLocation(cid, _) => ProposalAccessPolicy::Community(*cid),
Expand All @@ -88,6 +93,7 @@ impl<AccountId, Balance> ProposalAction<AccountId, Balance> {
ProposalAction::Petition(None, _) => ProposalAccessPolicy::Global,
ProposalAction::SpendNative(Some(cid), ..) => ProposalAccessPolicy::Community(*cid),
ProposalAction::SpendNative(None, ..) => ProposalAccessPolicy::Global,
ProposalAction::IssueSwapNativeOption(cid, ..) => ProposalAccessPolicy::Community(*cid),
}
}

Expand All @@ -108,6 +114,8 @@ impl<AccountId, Balance> ProposalAction<AccountId, Balance> {
ProposalActionIdentifier::Petition(*maybe_cid),
ProposalAction::SpendNative(maybe_cid, ..) =>
ProposalActionIdentifier::SpendNative(*maybe_cid),
ProposalAction::IssueSwapNativeOption(cid, ..) =>
ProposalActionIdentifier::IssueSwapNativeOption(*cid),
}
}

Expand All @@ -122,6 +130,7 @@ impl<AccountId, Balance> ProposalAction<AccountId, Balance> {
ProposalAction::SetInactivityTimeout(_) => true,
ProposalAction::Petition(_, _) => false,
ProposalAction::SpendNative(_, _, _) => false,
ProposalAction::IssueSwapNativeOption(..) => false,
}
}
}
Expand Down Expand Up @@ -153,7 +162,7 @@ impl<Moment: PartialEq> ProposalState<Moment> {
pub struct Proposal<Moment, AccountId, Balance> {
pub start: Moment,
pub start_cindex: CeremonyIndexType,
pub action: ProposalAction<AccountId, Balance>,
pub action: ProposalAction<AccountId, Balance, Moment>,
pub state: ProposalState<Moment>,
pub electorate_size: ReputationCountType,
}
1 change: 1 addition & 0 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub mod faucet;
pub mod reputation_commitments;
pub mod scheduler;
pub mod storage;
pub mod treasuries;
pub mod vouches;

pub use ep_core::*;
Expand Down
Loading

0 comments on commit dcc5c9b

Please sign in to comment.