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

Fees in community currency #190

Merged
merged 39 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1da41b4
setup fee payment in community currencies
pifragile Mar 22, 2022
7ace4ff
implement fee conversion factor
pifragile Mar 30, 2022
ff97003
fix f64 nostd issues
pifragile Mar 30, 2022
96d418a
remove clutter
pifragile Mar 30, 2022
3e6d6e4
fix float issue
pifragile Mar 30, 2022
3e9d4ec
move BalanceToCommunityBalance to communities pallet
pifragile Mar 30, 2022
0d11d41
implement test for conversion and fix bugs
pifragile Mar 30, 2022
66571b8
extract balances-tx-payment-extension crate
clangenb Mar 31, 2022
5b126e9
[balances] remove unused imports
clangenb Mar 31, 2022
09813ba
[balances] remove unused variables
clangenb Mar 31, 2022
4066d19
[balances-tx-payment-extension] tests work
clangenb Mar 31, 2022
9869fd2
[balances-tx-payment-extension] remove unused warnings
clangenb Mar 31, 2022
bfa17db
[balances-tx-payment-extension] separate aliases from conversion
clangenb Mar 31, 2022
1c7b6bd
[balances-tx-payment-extension] improve aliases
clangenb Mar 31, 2022
3a97f3b
add license headers
clangenb Mar 31, 2022
9e1c30f
[balances-tx-payment-ext] use improve type aliases
clangenb Mar 31, 2022
7eb4fcb
drop 'extension' on `balances-tx-payment-extension` name.
clangenb Mar 31, 2022
f672ef3
[primitives] add `EncointerBalanceConverter`
clangenb Mar 31, 2022
767064e
[encointer-balances] use balance converter from primitives
clangenb Mar 31, 2022
a068cda
Cargo.lock
clangenb Mar 31, 2022
67c86cb
[balance-tx-payment] incorporate more meaning in the fee_conversion_f…
clangenb Apr 1, 2022
a4cd038
move `BurnCredit` to `balances-tx-payement`
clangenb Apr 1, 2022
e92dcc3
[balances-tx-payment] simply fee calculation and tests
clangenb Apr 1, 2022
86ea1c7
[primitives] deterministic fungible to balance type conversion
clangenb Apr 1, 2022
62429fc
[primitives] use rstest
clangenb Apr 1, 2022
fc98120
[primitives] fix potential overflow in balance to fungible conversion
clangenb Apr 2, 2022
99efdda
[encointer-balances] move `balance_type_to_fungibles` tests to primit…
clangenb Apr 2, 2022
0996eff
add comment
clangenb Apr 2, 2022
15618b5
[encointer-balances] better test readability due to alias
clangenb Apr 2, 2022
68a5dec
fmt
clangenb Apr 2, 2022
0ee2477
fmt
clangenb Apr 2, 2022
3074363
[balance_conversion] use checked math
clangenb Apr 2, 2022
dd55a87
[encointer-balances] add comment about `InspectMetadata` implementation
clangenb Apr 2, 2022
f5a9350
[encointer-balances] adjust unit of `FeeConversionFactor` to be able …
clangenb Apr 2, 2022
7ea9b28
[encointer-balances] adjust unit of `FeeConversionFactor` to be able …
clangenb Apr 2, 2022
c91ace7
[balances-tx-payment] rename balance_to_community_balance to `apply_f…
clangenb Apr 2, 2022
74673ea
Merge branch 'master' into fees-in-community-currency
brenzi Apr 3, 2022
1958adb
rename ONE_CC -> ONE_FUNGIBLE_ASSET and add test for conversion factor
pifragile Apr 4, 2022
4338fb1
added some reasoning on decimals vs base2 and changed unittests to us…
brenzi Apr 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
189 changes: 118 additions & 71 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
'balances',
'balances-tx-payment',
'bazaar',
'bazaar/rpc',
'bazaar/rpc/runtime-api',
Expand Down
38 changes: 38 additions & 0 deletions balances-tx-payment/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "encointer-balances-tx-payment"
version = "0.1.0"
edition = "2021"

[dependencies]
pallet-encointer-balances = { path = "../balances", default-features = false }
pallet-encointer-communities = { path = "../communities", default-features = false }
encointer-primitives = { path = "../primitives", default-features = false }

# substrate dependencies
frame-support = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "master" }
frame-system = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "master" }
pallet-asset-tx-payment = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "master" }
pallet-transaction-payment = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "master" }
sp-runtime = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "master" }

[dev-dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
rstest = "0.12.0"
scale-info = { version = "2.0.1", default-features = false }
sp-io = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "master" }
test-utils = { path = "../test-utils" }

[features]
default = ["std"]
std = [
"pallet-encointer-balances/std",
"pallet-encointer-communities/std",
"encointer-primitives/std",

# substrate deps
"frame-support/std",
"frame-system/std",
"pallet-asset-tx-payment/std",
"pallet-transaction-payment/std",
"sp-runtime/std",
]
76 changes: 76 additions & 0 deletions balances-tx-payment/src/balance_conversion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) 2019 Alain Brenzikofer
// This file is part of Encointer
//
// Encointer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Encointer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Encointer. If not, see <http://www.gnu.org/licenses/>.

use crate::{AssetBalanceOf, AssetIdOf, BalanceOf};
use core::marker::PhantomData;
use encointer_primitives::{balances::EncointerBalanceConverter, communities::CommunityIdentifier};
use frame_support::traits::tokens::BalanceConversion;
use pallet_encointer_balances::Pallet as BalancesPallet;
use pallet_encointer_communities::{Config as CommunitiesConfig, Pallet as CommunitiesPallet};
use sp_runtime::traits::Convert;

/// 1 micro KSM with 12 decimals
pub const ONE_MICRO_KSM: u128 = 1_000_000;

/// 1 KSM with 12 decimals
pub const ONE_KSM: u128 = 1_000_000 * ONE_MICRO_KSM;

/// 1 Kilo-KSM with 12 decimals
pub const ONE_KILO_KSM: u128 = 1_000 * ONE_KSM;

/// Transforms the native token to the community currency
///
/// Assumptions:
/// * Native token has 12 decimals
/// * fee_conversion_factor is in Units 1 / [pKSM]
///
/// Applies the formula: Community Currency = KSM * FeeConversionFactor * Reward
pub fn apply_fee_conversion_factor(
balance: u128,
reward: u128,
fee_conversion_factor: u128,
) -> u128 {
brenzi marked this conversation as resolved.
Show resolved Hide resolved
return balance
.saturating_mul(reward)
.saturating_mul(fee_conversion_factor as u128)
.checked_div(ONE_KILO_KSM) // <- unit discrepancy: balance [pKSM] vs. fee_conversion_factor [KKSM]
.expect("Divisor != 0; qed")
}

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

impl<T> BalanceConversion<BalanceOf<T>, AssetIdOf<T>, AssetBalanceOf<T>>
for BalanceToCommunityBalance<T>
where
T: CommunitiesConfig + pallet_asset_tx_payment::Config,
CommunityIdentifier: From<AssetIdOf<T>>,
AssetBalanceOf<T>: From<u128>,
u128: From<BalanceOf<T>>,
{
type Error = frame_system::Error<T>;

fn to_asset_balance(
balance: BalanceOf<T>,
asset_id: AssetIdOf<T>,
) -> Result<AssetBalanceOf<T>, Self::Error> {
let fee_conversion_factor = BalancesPallet::<T>::fee_conversion_factor();
let reward = EncointerBalanceConverter::convert(CommunitiesPallet::<T>::nominal_income(
CommunityIdentifier::from(asset_id),
));

Ok(apply_fee_conversion_factor(balance.into(), reward, fee_conversion_factor).into())
}
}
55 changes: 55 additions & 0 deletions balances-tx-payment/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) 2019 Alain Brenzikofer
// This file is part of Encointer
//
// Encointer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Encointer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Encointer. If not, see <http://www.gnu.org/licenses/>.

#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::traits::fungibles;
use pallet_asset_tx_payment::HandleCredit;
use pallet_transaction_payment::OnChargeTransaction;

pub mod balance_conversion;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;

pub use balance_conversion::*;

pub type OnChargeTransactionOf<T> = <T as pallet_transaction_payment::Config>::OnChargeTransaction;

pub type BalanceOf<T> = <OnChargeTransactionOf<T> as OnChargeTransaction<T>>::Balance;

pub type FungiblesOf<T> = <T as pallet_asset_tx_payment::Config>::Fungibles;

pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;

pub type AssetBalanceOf<T> = <FungiblesOf<T> as fungibles::Inspect<AccountIdOf<T>>>::Balance;

pub type AssetIdOf<T> = <FungiblesOf<T> as fungibles::Inspect<AccountIdOf<T>>>::AssetId;

pub struct BurnCredit;
impl<T> HandleCredit<<T as frame_system::Config>::AccountId, pallet_encointer_balances::Pallet<T>>
for BurnCredit
where
T: frame_system::Config + pallet_encointer_balances::Config,
{
fn handle_credit(
_credit: fungibles::CreditOf<AccountIdOf<T>, pallet_encointer_balances::Pallet<T>>,
) {
// just doing nothing with the credit, will use the default implementation
// of fungibles an decrease total issuance.
}
}
70 changes: 70 additions & 0 deletions balances-tx-payment/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2019 Alain Brenzikofer
// This file is part of Encointer
//
// Encointer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Encointer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Encointer. If not, see <http://www.gnu.org/licenses/>.

//! Mock runtime for the encointer_communities module

use frame_support::pallet_prelude::GenesisBuild;

use encointer_primitives::scheduler::CeremonyPhaseType;
use test_utils::*;

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
type Block = frame_system::mocking::MockBlock<TestRuntime>;

frame_support::construct_runtime!(
pub enum TestRuntime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
EncointerScheduler: encointer_scheduler::{Pallet, Call, Storage, Config<T>, Event},
EncointerCommunities: pallet_encointer_communities::{Pallet, Call, Storage, Event<T>},
EncointerBalances: pallet_encointer_balances::{Pallet, Call, Storage, Event<T>},
}
);

// boilerplate
impl_frame_system!(TestRuntime);
impl_timestamp!(TestRuntime);
impl_encointer_scheduler!(TestRuntime);
impl_encointer_balances!(TestRuntime);
impl_encointer_communities!(TestRuntime);

// genesis values
#[allow(unused)]
pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default().build_storage::<TestRuntime>().unwrap();

encointer_scheduler::GenesisConfig::<TestRuntime> {
current_phase: CeremonyPhaseType::REGISTERING,
current_ceremony_index: 1,
phase_durations: vec![
(CeremonyPhaseType::REGISTERING, ONE_DAY),
(CeremonyPhaseType::ASSIGNING, ONE_DAY),
(CeremonyPhaseType::ATTESTING, ONE_DAY),
],
}
.assimilate_storage(&mut t)
.unwrap();

let conf =
pallet_encointer_communities::GenesisConfig { min_solar_trip_time_s: 1, max_speed_mps: 83 };
GenesisBuild::<TestRuntime>::assimilate_storage(&conf, &mut t).unwrap();

t.into()
}
23 changes: 23 additions & 0 deletions balances-tx-payment/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::{apply_fee_conversion_factor, ONE_MICRO_KSM};
use rstest::*;

/// one unit of community currency is a fixpoint with 64 fractional bits
const ONE_CC: u128 = 1 << 64;

#[rstest(ksm_balance, ceremony_reward, conversion_factor, expected_community_balance,
case(5 * ONE_MICRO_KSM, 20 * ONE_CC, 100_000, ONE_CC / 100),
case(10 * ONE_MICRO_KSM, 20 * ONE_CC, 100_000, ONE_CC / 50),
case(5 * ONE_MICRO_KSM, 10 * ONE_CC, 100_000, ONE_CC / 200),
case(5_000 * ONE_MICRO_KSM, 20 * ONE_CC, 100_000, ONE_CC * 10),
case(5 * ONE_MICRO_KSM, 20_000_000 * ONE_CC, 100_000, ONE_CC * 10_000),
case(5 * ONE_MICRO_KSM, 20_000_000 * ONE_CC, 50_000, ONE_CC * 5_000),
)]
fn balance_to_community_balance_works(
ksm_balance: u128,
ceremony_reward: u128,
conversion_factor: u128,
expected_community_balance: u128,
) {
let balance = apply_fee_conversion_factor(ksm_balance, ceremony_reward, conversion_factor);
assert_eq!(balance, expected_community_balance);
}
2 changes: 2 additions & 0 deletions balances/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ frame-support = { version = "4.0.0-dev", default-features = false,git = "https:/
frame-system = { version = "4.0.0-dev", default-features = false,git = "https://github.com/paritytech/substrate.git", branch = "master" }
sp-std = { version = "4.0.0-dev", default-features = false,git = "https://github.com/paritytech/substrate.git", branch = "master" }
sp-runtime = { version = "6.0.0", default-features = false,git = "https://github.com/paritytech/substrate.git", branch = "master" }
pallet-transaction-payment = { version = "4.0.0-dev" , default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "master" }
pallet-asset-tx-payment = { version = "4.0.0-dev" , default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "master" }

[dev-dependencies]
approx = "0.5.1"
Expand Down