ghost-node/pallets/networks/src/lib.rs
Uncle Stretch b4ef445281
make ability to have multiple default endpoints for the network
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2025-07-28 23:34:42 +03:00

791 lines
26 KiB
Rust

#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::large_enum_variant)]
#![allow(clippy::too_many_arguments)]
use frame_support::{
pallet_prelude::*,
storage::PrefixIterator,
traits::{tokens::fungible::Inspect, EnsureOrigin},
};
use frame_system::pallet_prelude::*;
use scale_info::TypeInfo;
use sp_runtime::{
curve::PiecewiseLinear,
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member},
DispatchResult,
};
use sp_std::{convert::TryInto, prelude::*};
pub use ghost_traits::networks::{
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
};
mod weights;
pub use crate::weights::WeightInfo;
pub use module::*;
#[cfg(any(feature = "runtime-benchmarks", test))]
mod benchmarking;
#[cfg(all(feature = "std", test))]
mod mock;
#[cfg(all(feature = "std", test))]
mod tests;
pub type BalanceOf<T> =
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub enum NetworkType {
Evm = 0,
Utxo = 1,
Undefined = 2,
}
impl Default for NetworkType {
fn default() -> Self {
NetworkType::Evm
}
}
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct NetworkData {
pub chain_name: Vec<u8>,
pub default_endpoints: Vec<Vec<u8>>,
pub gatekeeper: Vec<u8>,
pub topic_name: Vec<u8>,
pub network_type: NetworkType,
pub finality_delay: u64,
pub rate_limit_delay: u64,
pub block_distance: u64,
pub incoming_fee: u32,
pub outgoing_fee: u32,
}
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct BridgeAdjustment<Balance> {
pub bridged_out: Balance,
pub bridged_in: Balance,
}
pub struct BridgedInflationCurve<RewardCurve, T>(core::marker::PhantomData<(RewardCurve, T)>);
impl<Balance, RewardCurve, T> pallet_staking::EraPayout<Balance>
for BridgedInflationCurve<RewardCurve, T>
where
Balance: Default + AtLeast32BitUnsigned + Clone + Copy + From<u128>,
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::<T>::get();
let accumulated_commission = AccumulatedCommission::<T>::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)),
};
NullifyNeeded::<T>::set(true);
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::*;
#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The type used for the internal balance storage.
type Currency: Inspect<Self::AccountId>;
/// The type used as a unique network id.
type NetworkId: Parameter
+ Member
+ Parameter
+ AtLeast32BitUnsigned
+ Default
+ Copy
+ Ord
+ TypeInfo
+ MaybeSerializeDeserialize
+ MaxEncodedLen;
/// The origin required to register new network.
type RegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// The origin required to update network information.
type UpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// The origin required to remove network.
type RemoveOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// Weight information for extrinsics in this module.
type WeightInfo: WeightInfo;
}
#[pallet::error]
pub enum Error<T> {
/// Network already registered.
NetworkAlreadyRegistered,
/// Network does not exist.
NetworkDoesNotExist,
/// Gatekeeper address length not 42 or prefix `0x` missed.
WrongGatekeeperAddress,
/// Topic name length not 66 or prefix `0x` missed.
WrongTopicName,
}
#[pallet::event]
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
NetworkRegistered {
chain_id: T::NetworkId,
network: NetworkData,
},
NetworkNameUpdated {
chain_id: T::NetworkId,
chain_name: Vec<u8>,
},
NetworkEndpointUpdated {
chain_id: T::NetworkId,
index: u32,
endpoint: Vec<u8>,
},
NetworkEndpointRemoved {
chain_id: T::NetworkId,
index: u32,
},
NetworkEndpointAdded {
chain_id: T::NetworkId,
endpoint: Vec<u8>,
},
NetworkFinalityDelayUpdated {
chain_id: T::NetworkId,
finality_delay: u64,
},
NetworkRateLimitDelayUpdated {
chain_id: T::NetworkId,
rate_limit_delay: u64,
},
NetworkBlockDistanceUpdated {
chain_id: T::NetworkId,
block_distance: u64,
},
NetworkTypeUpdated {
chain_id: T::NetworkId,
network_type: NetworkType,
},
NetworkGatekeeperUpdated {
chain_id: T::NetworkId,
gatekeeper: Vec<u8>,
},
NetworkTopicNameUpdated {
chain_id: T::NetworkId,
topic_name: Vec<u8>,
},
NetworkIncomingFeeUpdated {
chain_id: T::NetworkId,
incoming_fee: u32,
},
NetworkOutgoingFeeUpdated {
chain_id: T::NetworkId,
outgoing_fee: u32,
},
NetworkRemoved {
chain_id: T::NetworkId,
},
}
#[pallet::storage]
#[pallet::getter(fn nullify_needed)]
pub type NullifyNeeded<T: Config> = StorageValue<_, bool, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn bridged_imbalance)]
pub type BridgedImbalance<T: Config> =
StorageValue<_, BridgeAdjustment<BalanceOf<T>>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn accumulated_commission)]
pub type AccumulatedCommission<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn networks)]
pub type Networks<T: Config> =
StorageMap<_, Twox64Concat, T::NetworkId, NetworkData, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn gatekeeper_amount)]
pub type GatekeeperAmount<T: Config> =
StorageMap<_, Twox64Concat, T::NetworkId, BalanceOf<T>, ValueQuery>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub networks: Vec<(T::NetworkId, Vec<u8>)>,
}
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { networks: vec![] }
}
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
if !self.networks.is_empty() {
self.networks
.iter()
.for_each(|(chain_id, network_metadata)| {
let network = NetworkData::decode(&mut &network_metadata[..])
.expect("Error decoding NetworkData");
Pallet::<T>::do_register_network(chain_id.clone(), network)
.expect("Error registering network");
});
}
}
}
#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
T::DbWeight::get().reads_writes(1, 1)
}
fn on_finalize(_: BlockNumberFor<T>) {
if Self::nullify_needed() {
Self::nullify_commission();
NullifyNeeded::<T>::put(false);
}
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::register_network(
network.chain_name.len() as u32,
network.default_endpoints
.iter()
.map(|endpoint| endpoint.len())
.sum::<usize>() as u32,
))]
pub fn register_network(
origin: OriginFor<T>,
chain_id: T::NetworkId,
network: NetworkData,
) -> DispatchResult {
T::RegisterOrigin::ensure_origin_or_root(origin)?;
Self::do_register_network(chain_id, network)
}
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::update_network_name(
chain_name.len() as u32,
))]
pub fn update_network_name(
origin: OriginFor<T>,
chain_id: T::NetworkId,
chain_name: Vec<u8>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_name(chain_id, chain_name)
}
#[pallet::call_index(2)]
#[pallet::weight(T::WeightInfo::update_network_endpoint(
maybe_endpoint
.as_ref()
.map(|endpoint| endpoint.len())
.unwrap_or_default() as u32
))]
pub fn update_network_endpoint(
origin: OriginFor<T>,
chain_id: T::NetworkId,
maybe_index: Option<u32>,
maybe_endpoint: Option<Vec<u8>>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_endpoint(chain_id, maybe_index, maybe_endpoint)
}
#[pallet::call_index(3)]
#[pallet::weight(T::WeightInfo::update_network_finality_delay())]
pub fn update_network_finality_delay(
origin: OriginFor<T>,
chain_id: T::NetworkId,
finality_delay: u64,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_finality_delay(chain_id, finality_delay)
}
#[pallet::call_index(4)]
#[pallet::weight(T::WeightInfo::update_network_rate_limit_delay())]
pub fn update_network_rate_limit_delay(
origin: OriginFor<T>,
chain_id: T::NetworkId,
rate_limit_delay: u64,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_rate_limit_delay(chain_id, rate_limit_delay)
}
#[pallet::call_index(5)]
#[pallet::weight(T::WeightInfo::update_network_block_distance())]
pub fn update_network_block_distance(
origin: OriginFor<T>,
chain_id: T::NetworkId,
block_distance: u64,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_block_distance(chain_id, block_distance)
}
#[pallet::call_index(6)]
#[pallet::weight(T::WeightInfo::update_network_type())]
pub fn update_network_type(
origin: OriginFor<T>,
chain_id: T::NetworkId,
network_type: NetworkType,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_type(chain_id, network_type)
}
#[pallet::call_index(7)]
#[pallet::weight(T::WeightInfo::update_network_gatekeeper())]
pub fn update_network_gatekeeper(
origin: OriginFor<T>,
chain_id: T::NetworkId,
gatekeeper: Vec<u8>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_gatekeeper(chain_id, gatekeeper)
}
#[pallet::call_index(8)]
#[pallet::weight(T::WeightInfo::update_network_topic_name())]
pub fn update_network_topic_name(
origin: OriginFor<T>,
chain_id: T::NetworkId,
topic_name: Vec<u8>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_topic_name(chain_id, topic_name)
}
#[pallet::call_index(9)]
#[pallet::weight(T::WeightInfo::update_incoming_network_fee())]
pub fn update_incoming_network_fee(
origin: OriginFor<T>,
chain_id: T::NetworkId,
incoming_fee: u32,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_incoming_network_fee(chain_id, incoming_fee)
}
#[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::update_outgoing_network_fee())]
pub fn update_outgoing_network_fee(
origin: OriginFor<T>,
chain_id: T::NetworkId,
outgoing_fee: u32,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_outgoing_network_fee(chain_id, outgoing_fee)
}
#[pallet::call_index(11)]
#[pallet::weight(T::WeightInfo::remove_network())]
pub fn remove_network(origin: OriginFor<T>, chain_id: T::NetworkId) -> DispatchResult {
T::RemoveOrigin::ensure_origin_or_root(origin)?;
Self::do_remove_network(chain_id)
}
}
}
impl<T: Config> Pallet<T> {
/// Register a new network.
pub fn do_register_network(chain_id: T::NetworkId, network: NetworkData) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(
maybe_network.is_none(),
Error::<T>::NetworkAlreadyRegistered
);
*maybe_network = Some(network.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkRegistered { chain_id, network });
Ok(())
}
/// Remove existent network.
pub fn do_remove_network(chain_id: T::NetworkId) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
*maybe_network = None;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkRemoved { chain_id });
Ok(())
}
/// Update existent network name.
pub fn do_update_network_name(chain_id: T::NetworkId, chain_name: Vec<u8>) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.chain_name = chain_name.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkNameUpdated {
chain_id,
chain_name,
});
Ok(())
}
/// Update existent network default endpoint.
pub fn do_update_network_endpoint(
chain_id: T::NetworkId,
maybe_index: Option<u32>,
maybe_endpoint: Option<Vec<u8>>,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let updated_network = maybe_network.as_mut().unwrap();
match (maybe_index, maybe_endpoint) {
(Some(index), Some(endpoint)) => {
if let Some(previous_endpoint) =
updated_network.default_endpoints.get_mut(index as usize)
{
*previous_endpoint = endpoint.clone();
Self::deposit_event(Event::<T>::NetworkEndpointUpdated {
chain_id,
index,
endpoint,
});
}
}
(None, Some(endpoint)) => {
updated_network.default_endpoints.push(endpoint.clone());
Self::deposit_event(Event::<T>::NetworkEndpointAdded { chain_id, endpoint });
}
(Some(index), None) => {
updated_network.default_endpoints.remove(index as usize);
Self::deposit_event(Event::<T>::NetworkEndpointRemoved { chain_id, index });
}
(None, None) => {}
}
*maybe_network = Some(updated_network.clone());
Ok(())
})?;
Ok(())
}
/// Update existent network default finality delay.
pub fn do_update_network_finality_delay(
chain_id: T::NetworkId,
finality_delay: u64,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.finality_delay = finality_delay;
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkFinalityDelayUpdated {
chain_id,
finality_delay,
});
Ok(())
}
/// Update existent network default rate limit delay.
pub fn do_update_network_rate_limit_delay(
chain_id: T::NetworkId,
rate_limit_delay: u64,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.rate_limit_delay = rate_limit_delay;
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkRateLimitDelayUpdated {
chain_id,
rate_limit_delay,
});
Ok(())
}
/// Update existent network default max distance between blocks.
pub fn do_update_network_block_distance(
chain_id: T::NetworkId,
block_distance: u64,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.block_distance = block_distance;
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkBlockDistanceUpdated {
chain_id,
block_distance,
});
Ok(())
}
/// Update existent network type.
pub fn do_update_network_type(
chain_id: T::NetworkId,
network_type: NetworkType,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.network_type = network_type.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkTypeUpdated {
chain_id,
network_type,
});
Ok(())
}
/// Update existent network gatekeeper.
pub fn do_update_network_gatekeeper(
chain_id: T::NetworkId,
gatekeeper: Vec<u8>,
) -> DispatchResult {
ensure!(
gatekeeper.len() == 42 && gatekeeper[0] == 48 && gatekeeper[1] == 120,
Error::<T>::WrongGatekeeperAddress
);
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.gatekeeper = gatekeeper.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkGatekeeperUpdated {
chain_id,
gatekeeper,
});
Ok(())
}
/// Update existent network gatekeeper's topic name.
pub fn do_update_network_topic_name(
chain_id: T::NetworkId,
topic_name: Vec<u8>,
) -> DispatchResult {
ensure!(
topic_name.len() == 66 && topic_name[0] == 48 && topic_name[1] == 120,
Error::<T>::WrongTopicName
);
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.topic_name = topic_name.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkTopicNameUpdated {
chain_id,
topic_name,
});
Ok(())
}
pub fn do_update_incoming_network_fee(
chain_id: T::NetworkId,
incoming_fee: u32,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.incoming_fee = incoming_fee.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkIncomingFeeUpdated {
chain_id,
incoming_fee,
});
Ok(())
}
pub fn do_update_outgoing_network_fee(
chain_id: T::NetworkId,
outgoing_fee: u32,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap();
net.outgoing_fee = outgoing_fee.clone();
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkOutgoingFeeUpdated {
chain_id,
outgoing_fee,
});
Ok(())
}
}
impl<T: Config> NetworkDataBasicHandler for Pallet<T> {
type NetworkId = T::NetworkId;
}
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
fn get(n: &Self::NetworkId) -> Option<NetworkData> {
Networks::<T>::get(n)
}
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
Networks::<T>::iter()
}
fn is_nullification_period() -> bool {
NullifyNeeded::<T>::get()
}
}
impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T> {
fn register(chain_id: Self::NetworkId, network: NetworkData) -> DispatchResult {
Self::do_register_network(chain_id, network)
}
fn remove(chain_id: Self::NetworkId) -> DispatchResult {
Self::do_remove_network(chain_id)
}
fn increase_gatekeeper_amount(
network_id: &T::NetworkId,
amount: &BalanceOf<T>,
) -> Result<BalanceOf<T>, ()> {
let new_gatekeeper_amount =
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount
.checked_add(amount)
{
Some(value) => {
*gatekeeper_amount = value;
Ok(value)
}
None => Err(()),
})?;
Ok(new_gatekeeper_amount)
}
fn decrease_gatekeeper_amount(
network_id: &T::NetworkId,
amount: &BalanceOf<T>,
) -> Result<BalanceOf<T>, ()> {
let new_gatekeeper_amount =
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount
.checked_sub(amount)
{
Some(value) => {
*gatekeeper_amount = value;
Ok(value)
}
None => Err(()),
})?;
Ok(new_gatekeeper_amount)
}
fn accumulate_outgoing_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
let new_bridged_out_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| {
match bridged_imbalance.bridged_out.checked_add(amount) {
Some(value) => {
(*bridged_imbalance).bridged_out = value;
Ok(value)
}
None => Err(()),
}
})?;
Ok(new_bridged_out_amount)
}
fn accumulate_incoming_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
let new_bridged_in_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| {
match bridged_imbalance.bridged_in.checked_add(amount) {
Some(value) => {
(*bridged_imbalance).bridged_in = value;
Ok(value)
}
None => Err(()),
}
})?;
Ok(new_bridged_in_amount)
}
fn accumulate_commission(commission: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
AccumulatedCommission::<T>::mutate(|accumulated| {
match accumulated.checked_add(commission) {
Some(value) => {
*accumulated = value;
Ok(value)
}
None => Err(()),
}
})
}
fn nullify_commission() {
AccumulatedCommission::<T>::set(Default::default());
}
fn trigger_nullification() {
if NullifyNeeded::<T>::get() {
Self::nullify_commission();
NullifyNeeded::<T>::put(false);
} else {
NullifyNeeded::<T>::put(true);
}
}
}