From b3f85f426c0c747bfb0f7010d700b7dafc4ee5f4 Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Fri, 30 May 2025 19:03:50 +0300 Subject: [PATCH] extend pallet ghost-networks and create BridgedInflationCurve Signed-off-by: Uncle Stinky --- Cargo.lock | 4 +- pallets/networks/Cargo.toml | 40 ++--- pallets/networks/src/lib.rs | 147 ++++++++++++++++- pallets/networks/src/mock.rs | 32 +++- pallets/networks/src/tests.rs | 284 ++++++++++++++++++++++++++++++++- pallets/traits/src/networks.rs | 13 +- 6 files changed, 489 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bec2e00..6bfebf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "ghost-networks" -version = "0.7.197" +version = "0.1.2" dependencies = [ "frame-benchmarking", "frame-support", @@ -3656,6 +3656,8 @@ dependencies = [ "ghost-core-primitives", "ghost-traits", "pallet-balances", + "pallet-staking", + "pallet-staking-reward-curve", "parity-scale-codec", "scale-info", "sp-io 30.0.0", diff --git a/pallets/networks/Cargo.toml b/pallets/networks/Cargo.toml index 3f97642..165a5f2 100644 --- a/pallets/networks/Cargo.toml +++ b/pallets/networks/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ghost-networks" +version = "0.1.2" license.workspace = true authors.workspace = true -version.workspace = true edition.workspace = true homepage.workspace = true repository.workspace = true @@ -14,36 +14,40 @@ codec = { workspace = true, features = ["max-encoded-len"] } frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } +pallet-staking = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } ghost-traits = { workspace = true } [dev-dependencies] primitives = { workspace = true } -pallet-balances = { workspace = true } sp-io = { workspace = true } +pallet-balances = { workspace = true } +pallet-staking-reward-curve = { workspace = true } [features] default = ["std"] std = [ - "scale-info/std", - "codec/std", - "frame-support/std", - "frame-system/std", - "frame-benchmarking?/std", - "sp-runtime/std", - "sp-std/std", - "sp-io/std", - "ghost-traits/std", - "pallet-balances/std", + "scale-info/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "frame-benchmarking?/std", + "sp-runtime/std", + "sp-std/std", + "sp-io/std", + "ghost-traits/std", + "pallet-staking/std", + "pallet-balances/std", ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", ] diff --git a/pallets/networks/src/lib.rs b/pallets/networks/src/lib.rs index b347044..eaa1f8e 100644 --- a/pallets/networks/src/lib.rs +++ b/pallets/networks/src/lib.rs @@ -4,15 +4,17 @@ use frame_support::{ pallet_prelude::*, - storage::PrefixIterator, traits::EnsureOrigin, + storage::PrefixIterator, traits::{tokens::fungible::Inspect, EnsureOrigin}, }; use frame_system::pallet_prelude::*; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Member}, + traits::{CheckedSub, CheckedAdd, AtLeast32BitUnsigned, Member}, + curve::PiecewiseLinear, DispatchResult, }; use sp_std::prelude::*; +use sp_std::convert::TryInto; pub use ghost_traits::networks::{ NetworkDataBasicHandler, NetworkDataInspectHandler, @@ -31,6 +33,10 @@ mod mock; #[cfg(all(feature = "std", test))] mod tests; +pub type BalanceOf = <::Currency as Inspect< + ::AccountId, +>>::Balance; + #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum NetworkType { Evm = 0, @@ -55,6 +61,48 @@ pub struct NetworkData { pub outgoing_fee: u32, } +#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct BridgeAdjustment { + bridged_out: Balance, + bridged_in: Balance, +} + +pub struct BridgedInflationCurve(core::marker::PhantomData<(RewardCurve, T)>); +impl pallet_staking::EraPayout for BridgedInflationCurve +where + Balance: Default + AtLeast32BitUnsigned + Clone + Copy + From, + RewardCurve: Get<&'static PiecewiseLinear<'static>>, + T: Config, +{ + fn era_payout( + total_staked: Balance, + total_issuance: Balance, + _era_duration_in_millis: u64, + ) -> (Balance, Balance) { + let piecewise_linear = RewardCurve::get(); + let bridge_adjustment = BridgedImbalance::::get(); + let accumulated_commission = AccumulatedCommission::::get(); + + let bridged_out: u128 = bridge_adjustment.bridged_out.try_into().unwrap_or_default(); + let bridged_in: u128 = bridge_adjustment.bridged_in.try_into().unwrap_or_default(); + let accumulated_commission: u128 = accumulated_commission.try_into().unwrap_or_default(); + + let accumulated_balance = Balance::from(accumulated_commission); + let adjusted_issuance = match bridged_out > bridged_in { + true => total_issuance.saturating_add(Balance::from(bridged_out - bridged_in)), + false => total_issuance.saturating_sub(Balance::from(bridged_in - bridged_out)), + }; + + match piecewise_linear + .calculate_for_fraction_times_denominator(total_staked, adjusted_issuance) + .checked_mul(&accumulated_balance) + .and_then(|product| product.checked_div(&adjusted_issuance)) { + Some(payout) => (payout, accumulated_balance.saturating_sub(payout)), + None => (Balance::default(), Balance::default()), + } + } +} + #[frame_support::pallet] pub mod module { use super::*; @@ -63,6 +111,9 @@ pub mod module { pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The type used for the internal balance storage. + type Currency: Inspect; + /// The type used as a unique network id. type NetworkId: Parameter + Member @@ -114,11 +165,31 @@ pub mod module { NetworkRemoved { chain_id: T::NetworkId }, } + #[pallet::storage] + #[pallet::getter(fn bridged_imbalance)] + pub type BridgedImbalance = + StorageValue<_, BridgeAdjustment>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn accumulated_commission)] + pub type AccumulatedCommission = + StorageValue<_, BalanceOf, ValueQuery>; + #[pallet::storage] #[pallet::getter(fn networks)] pub type Networks = StorageMap<_, Twox64Concat, T::NetworkId, NetworkData, OptionQuery>; + #[pallet::storage] + #[pallet::getter(fn gatekeeper_amount)] + pub type GatekeeperAmount = StorageMap< + _, + Twox64Concat, + T::NetworkId, + BalanceOf, + ValueQuery, + >; + #[pallet::genesis_config] pub struct GenesisConfig { pub networks: Vec<(T::NetworkId, Vec)>, @@ -527,7 +598,7 @@ impl NetworkDataInspectHandler for Pallet { } } -impl NetworkDataMutateHandler for Pallet { +impl NetworkDataMutateHandler> for Pallet { fn register(chain_id: Self::NetworkId, network: NetworkData) -> DispatchResult { Self::do_register_network(chain_id, network) } @@ -535,4 +606,74 @@ impl NetworkDataMutateHandler for Pallet { fn remove(chain_id: Self::NetworkId) -> DispatchResult { Self::do_remove_network(chain_id) } + + fn increase_gatekeeper_amount( + network_id: &T::NetworkId, + amount: &BalanceOf, + ) -> Result<(BalanceOf, BalanceOf), ()> { + let new_bridged_in_amount = BridgedImbalance::::mutate(|bridged_imbalance| { + match bridged_imbalance.bridged_in.checked_add(amount) { + Some(value) => { + (*bridged_imbalance).bridged_in = value; + Ok(value) + }, + None => Err(()) + } + })?; + + let new_gatekeeper_amount = GatekeeperAmount::::mutate(network_id, |gatekeeper_amount| { + match gatekeeper_amount.checked_add(amount) { + Some(value) => { + *gatekeeper_amount = value; + Ok(value) + }, + None => Err(()) + } + })?; + + Ok((new_gatekeeper_amount, new_bridged_in_amount)) + } + + fn decrease_gatekeeper_amount( + network_id: &T::NetworkId, + amount: &BalanceOf, + ) -> Result<(BalanceOf, BalanceOf), ()> { + let new_gatekeeper_amount = GatekeeperAmount::::mutate(network_id, |gatekeeper_amount| { + match gatekeeper_amount.checked_sub(amount) { + Some(value) => { + *gatekeeper_amount = value; + Ok(value) + }, + None => Err(()) + } + })?; + + let new_bridged_out_amount = BridgedImbalance::::mutate(|bridged_imbalance| { + match bridged_imbalance.bridged_out.checked_add(amount) { + Some(value) => { + (*bridged_imbalance).bridged_out = value; + Ok(value) + }, + None => Err(()) + } + })?; + + Ok((new_gatekeeper_amount, new_bridged_out_amount)) + } + + fn accumulate_commission(commission: &BalanceOf) -> Result, ()> { + AccumulatedCommission::::mutate(|accumulated| { + match accumulated.checked_add(commission) { + Some(value) => { + *accumulated = value; + Ok(value) + }, + None => Err(()), + } + }) + } + + fn nullify_commission() { + AccumulatedCommission::::set(Default::default()); + } } diff --git a/pallets/networks/src/mock.rs b/pallets/networks/src/mock.rs index 96579d6..09eca1a 100644 --- a/pallets/networks/src/mock.rs +++ b/pallets/networks/src/mock.rs @@ -1,19 +1,25 @@ -use crate as ghost_networks; +use crate::{self as ghost_networks}; use frame_system::EnsureSignedBy; use frame_support::{ - construct_runtime, ord_parameter_types, parameter_types, traits::{ConstU128, ConstU32, Everything} + construct_runtime, ord_parameter_types, parameter_types, + traits::{ConstU128, ConstU32, Everything}, }; pub use primitives::{ AccountId, Balance, Nonce, BlockNumber, Hash, ReserveIdentifier, FreezeIdentifier, }; use sp_runtime::{ - traits::{BlakeTwo256, AccountIdLookup}, - BuildStorage, + curve::PiecewiseLinear, + traits::{AccountIdLookup, BlakeTwo256}, + BuildStorage }; parameter_types! { pub const BlockHashCount: BlockNumber = 250; + pub static SlashDeferDuration: u32 = 0; + pub static Period: BlockNumber = 5; + pub static Offset: BlockNumber = 0; + pub static MaxControllersInDeprecationBatch: u32 = 5_000; } impl frame_system::Config for Test { @@ -64,6 +70,21 @@ impl pallet_balances::Config for Test { type MaxFreezes = ConstU32<50>; } +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_006_900, + max_inflation: 1_000_000, + ideal_stake: 0_690_000, + falloff: 0_050_000, + max_piece_count: 100, + test_precision: 0_005_000, + ); +} + +parameter_types! { + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; +} + ord_parameter_types! { pub const RegistererAccount: AccountId = AccountId::from([1u8; 32]); pub const UpdaterAccount: AccountId = AccountId::from([2u8; 32]); @@ -73,6 +94,7 @@ ord_parameter_types! { impl ghost_networks::Config for Test { type RuntimeEvent = RuntimeEvent; + type Currency = Balances; type NetworkId = u32; type RegisterOrigin = EnsureSignedBy::; type UpdateOrigin = EnsureSignedBy::; @@ -80,7 +102,7 @@ impl ghost_networks::Config for Test { type WeightInfo = crate::weights::SubstrateWeight; } -type Block = frame_system::mocking::MockBlockU32; +type Block = frame_system::mocking::MockBlock; construct_runtime!( pub enum Test { diff --git a/pallets/networks/src/tests.rs b/pallets/networks/src/tests.rs index 407784f..8076440 100644 --- a/pallets/networks/src/tests.rs +++ b/pallets/networks/src/tests.rs @@ -1,16 +1,16 @@ use mock::{ ExtBuilder, System, RegistererAccount, UpdaterAccount, RemoverAccount, - RandomAccount, GhostNetworks, Test, RuntimeEvent, RuntimeOrigin, + RandomAccount, GhostNetworks, Test, RuntimeEvent, RuntimeOrigin, RewardCurve, }; use frame_support::{assert_err, assert_ok}; use sp_runtime::DispatchError; +use pallet_staking::EraPayout; use super::*; fn prepare_network_data() -> (u32, NetworkData) { (1u32, NetworkData { chain_name: "Ethereum".into(), - default_endpoint: - "https:://some-endpoint.my-server.com/v1/my-super-secret-key".into(), + default_endpoint: "https:://some-endpoint.my-server.com/v1/my-super-secret-key".into(), finality_delay: Some(69), release_delay: Some(69), network_type: NetworkType::Evm, @@ -635,3 +635,281 @@ fn could_not_remove_non_existent_network() { assert_eq!(Networks::::get(chain_id), None); }); } + +#[test] +fn bridge_storage_is_empty_by_default() { + ExtBuilder::build() + .execute_with(|| { + assert_eq!(AccumulatedCommission::::get(), 0); + assert_eq!(BridgedImbalance::::get(), + BridgeAdjustment::default()); + }); +} + +#[test] +fn gatekeeper_amount_changes_correctly() { + ExtBuilder::build() + .execute_with(|| { + let chain_id: u32 = 1; + let amount_in: u128 = 420; + let amount_out: u128 = 69; + let result = amount_in - 3 * amount_out; + + assert_eq!(GatekeeperAmount::::get(&chain_id), 0); + assert_eq!(BridgedImbalance::::get(), + BridgeAdjustment::default()); + + assert_ok!(GhostNetworks::increase_gatekeeper_amount(&chain_id, &amount_in)); + assert_ok!(GhostNetworks::decrease_gatekeeper_amount(&chain_id, &amount_out)); + assert_ok!(GhostNetworks::decrease_gatekeeper_amount(&chain_id, &amount_out)); + assert_ok!(GhostNetworks::decrease_gatekeeper_amount(&chain_id, &amount_out)); + + assert_eq!(GatekeeperAmount::::get(&chain_id), result); + assert_eq!(BridgedImbalance::::get(), BridgeAdjustment { + bridged_out: 3 * amount_out, + bridged_in: amount_in }); + }); +} + +#[test] +fn commission_accumulation_is_correct() { + ExtBuilder::build() + .execute_with(|| { + let commission_first: u128 = 420; + let commission_second: u128 = 69; + let result = commission_first + commission_second; + + assert_eq!(AccumulatedCommission::::get(), 0); + assert_ok!(GhostNetworks::accumulate_commission(&commission_first)); + assert_ok!(GhostNetworks::accumulate_commission(&commission_second)); + assert_eq!(AccumulatedCommission::::get(), result); + }); +} + +#[test] +fn commission_overflow_and_underflow_emits_error() { + ExtBuilder::build() + .execute_with(|| { + let commission: u128 = u128::MAX - 69; + assert_eq!(AccumulatedCommission::::get(), 0); + assert_ok!(GhostNetworks::accumulate_commission(&commission)); + assert_err!(GhostNetworks::accumulate_commission(&commission), ()); + assert_eq!(AccumulatedCommission::::get(), commission); + }); +} + +#[test] +fn gatekeeper_amount_overflow_and_underflow_emits_error() { + ExtBuilder::build() + .execute_with(|| { + let chain_id: u32 = 1; + let commission: u128 = u128::MAX - 69; + assert_eq!(GatekeeperAmount::::get(&chain_id), 0); + assert_ok!(GhostNetworks::increase_gatekeeper_amount( + &chain_id, + &commission, + ), (commission, commission)); + assert_err!(GhostNetworks::increase_gatekeeper_amount( + &chain_id, + &commission, + ), ()); + assert_eq!(GatekeeperAmount::::get(&chain_id), commission); + assert_ok!(GhostNetworks::decrease_gatekeeper_amount( + &chain_id, + &commission, + ), (0, commission)); + assert_err!(GhostNetworks::decrease_gatekeeper_amount( + &chain_id, + &commission, + ), ()); + assert_eq!(GatekeeperAmount::::get(&chain_id), 0); + assert_eq!(BridgedImbalance::::get(), BridgeAdjustment { + bridged_out: commission, + bridged_in: commission, + }); + }); +} + +#[test] +fn bridged_amount_overflow_and_underflow_emits_error() { + ExtBuilder::build() + .execute_with(|| { + let chain_id_first: u32 = 1; + let chain_id_second: u32 = 2; + let commission: u128 = u128::MAX - 69; + assert_eq!(BridgedImbalance::::get(), BridgeAdjustment { + bridged_out: 0, + bridged_in: 0, + }); + assert_ok!(GhostNetworks::increase_gatekeeper_amount( + &chain_id_first, + &commission, + ), (commission, commission)); + assert_err!(GhostNetworks::increase_gatekeeper_amount( + &chain_id_second, + &commission, + ), ()); + assert_err!(GhostNetworks::increase_gatekeeper_amount( + &chain_id_first, + &u128::MAX, + ), ()); + assert_err!(GhostNetworks::increase_gatekeeper_amount( + &chain_id_first, + &commission, + ), ()); + assert_eq!(GatekeeperAmount::::get(&chain_id_first), commission); + assert_eq!(GatekeeperAmount::::get(&chain_id_second), 0); + assert_err!(GhostNetworks::decrease_gatekeeper_amount( + &chain_id_second, + &commission, + ), ()); + }); +} + +#[test] +fn accumulated_commission_could_be_nullified() { + ExtBuilder::build() + .execute_with(|| { + let commission_first: u128 = 420; + let commission_second: u128 = 69; + + assert_eq!(AccumulatedCommission::::get(), 0); + assert_ok!(GhostNetworks::accumulate_commission( + &commission_first + ), commission_first); + assert_ok!(GhostNetworks::accumulate_commission( + &commission_second, + ), commission_first + commission_second); + assert_eq!(AccumulatedCommission::::get(), + commission_first + commission_second); + GhostNetworks::nullify_commission(); + assert_eq!(AccumulatedCommission::::get(), 0); + }); +} + +#[test] +fn bridged_inlation_reward_works() { + ExtBuilder::build() + .execute_with(|| { + let chain_id: u32 = 1; + let amount: u128 = 1337 * 1_000_000_000; + let commission: u128 = amount / 100; // 1% commission + let total_staked_ideal: u128 = 69; + let total_staked_not_ideal: u128 = 68; + let total_issuance: u128 = 100; + + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000, + total_issuance * 1_000, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000, + 0), (0, 0)); + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000, + total_issuance * 1_000, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000, + 0), (0, 0)); + + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000, 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000, 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000_000_000_000_000, 0), (0, 0)); + + assert_ok!(GhostNetworks::accumulate_commission(&commission)); + assert_ok!(GhostNetworks::increase_gatekeeper_amount(&chain_id, &amount)); + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000, + total_issuance * 1_000 + amount, + 0), (commission, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000 + amount, + 0), (commission, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000 + amount, + 0), (commission, 0)); + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000, + total_issuance * 1_000 + amount, + 0), (13177472000, 192528000)); + assert_eq!(13177472000 + 192528000, commission); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000 + amount, + 0), (13177568884, 192431116)); + assert_eq!(13177568884 + 192431116, commission); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000 + amount, + 0), (13177568884, 192431116)); + assert_eq!(13177568884 + 192431116, commission); + + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000 + amount, 0), + (92386700, 13277613300)); + assert_eq!(92386700 + 13277613300, commission); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000 + amount, 0), + (92253000, 13277747000)); + assert_eq!(92253000 + 13277747000, commission); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000_000_000_000_000 + amount, 0), + (92253000, 13277747000)); + assert_eq!(92253000 + 13277747000, commission); + + GhostNetworks::nullify_commission(); + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000, + total_issuance * 1_000 + amount, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000 + amount, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000 + amount, + 0), (0, 0)); + + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000, + total_issuance * 1_000 + amount, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000, + total_issuance * 1_000_000_000_000 + amount, + 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + total_staked_not_ideal * 1_000_000_000_000_000_000_000_000, + total_issuance * 1_000_000_000_000_000_000_000_000 + amount, + 0), (0, 0)); + + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000 + amount, 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000 + amount, 0), (0, 0)); + assert_eq!(BridgedInflationCurve::::era_payout( + 1, total_issuance * 1_000_000_000_000_000_000_000_000 + amount, 0), (0, 0)); + }); +} diff --git a/pallets/traits/src/networks.rs b/pallets/traits/src/networks.rs index 858ca6c..c527293 100644 --- a/pallets/traits/src/networks.rs +++ b/pallets/traits/src/networks.rs @@ -23,7 +23,18 @@ pub trait NetworkDataInspectHandler: NetworkDataBasicHandler { fn iter() -> PrefixIterator<(Self::NetworkId, Network)>; } -pub trait NetworkDataMutateHandler: NetworkDataInspectHandler { +pub trait NetworkDataMutateHandler: NetworkDataInspectHandler { fn register(chain_id: Self::NetworkId, network: Network) -> DispatchResult; fn remove(chain_id: Self::NetworkId) -> DispatchResult; + + fn increase_gatekeeper_amount( + chain_id: &Self::NetworkId, + amount: &Balance, + ) -> Result<(Balance, Balance), ()>; + fn decrease_gatekeeper_amount( + chain_id: &Self::NetworkId, + amount: &Balance, + ) -> Result<(Balance, Balance), ()>; + fn accumulate_commission(commission: &Balance) -> Result; + fn nullify_commission(); }