ghost-node/pallets/networks/src/lib.rs
Uncle Stinky 59b5356613
make decimals part of network data
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
2026-09-10 21:40:06 +03:00

886 lines
31 KiB
Rust

#![cfg_attr(not(feature = "std"), no_std)]
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,
Saturating, UniqueSaturatedInto,
},
DispatchResult, Perbill,
};
use sp_std::{convert::TryInto, prelude::*};
use ghost_traits::networks::{
NetworkDataBasicHandler, NetworkDataInspectHandler, NetworkDataMutateHandler,
};
use ghost_helpers::networks::{
MAX_ENDPOINT_LEN, MAX_GATEKEEPER_LEN, MAX_SELECTOR_LEN,
NetworkData, NetworkType, NetworkCurve, NetworkInitiation,
};
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(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct NetworkImbalanceState<Balance> {
pub outgoing: Balance,
pub incoming: Balance,
pub curve_share: 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
+ Copy
+ From<BalanceOf<T>>
+ AtLeast32BitUnsigned
+ num_traits::ops::wrapping::WrappingAdd
+ num_traits::ops::overflowing::OverflowingAdd
+ sp_std::ops::AddAssign
+ sp_std::ops::Not<Output = Balance>
+ sp_std::ops::Shl<Output = Balance>
+ sp_std::ops::Shr<Output = Balance>
+ sp_std::ops::BitAnd<Balance, Output = Balance>,
RewardCurve: Get<&'static PiecewiseLinear<'static>>,
T: Config,
{
fn era_payout(
total_staked: Balance,
total_issuance: Balance,
_era_duration_in_millis: u64,
) -> (Balance, Balance) {
let reward_curve = RewardCurve::get();
let state = NetworkImbalance::<T>::take();
let accumulated_commission: Balance = state.curve_share.into();
let adjusted_issuance: Balance = total_issuance
.saturating_add(state.outgoing.into())
.saturating_sub(state.incoming.into());
let estimated_reward =
reward_curve.calculate_for_fraction_times_denominator(
total_staked,
adjusted_issuance,
);
let payout: Balance = sp_runtime::helpers_128bit::multiply_by_rational_with_rounding(
estimated_reward.unique_saturated_into(),
accumulated_commission.unique_saturated_into(),
adjusted_issuance.unique_saturated_into(),
sp_runtime::Rounding::NearestPrefUp,
)
.map(|result| result.unique_saturated_into())
.unwrap_or_default();
let rest_payout = accumulated_commission.saturating_sub(payout);
(payout, rest_payout)
}
}
#[frame_support::pallet]
pub mod module {
use super::*;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
#[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>;
#[pallet::constant]
type MaxNetworks: Get<u32>;
/// 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,
/// Could not store networks into bounded vector.
TooManyNetworks,
/// Selector length should always be 4.
InvalidSelectorLen,
/// Index is out of possible range.
IndexOutOfBounds,
/// No more default endpoints available to store.
TooManyEndpoints,
/// Network type does not exist under specified curve.
NetworkTypeDoesNotExist,
}
#[pallet::event]
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
NetworkRegistered { chain_id: T::NetworkId },
NetworkSelectorUpdated { chain_id: T::NetworkId },
NetworkEndpointUpdated { index: u32, chain_id: T::NetworkId },
NetworkEndpointRemoved { index: u32, chain_id: T::NetworkId },
NetworkEndpointAdded { chain_id: T::NetworkId },
NetworkFinalityDelayUpdated { chain_id: T::NetworkId, finality_delay: u64 },
NetworkRateLimitDelayUpdated { chain_id: T::NetworkId, rate_limit_delay: u64 },
NetworkBlockDeviationUpdated { chain_id: T::NetworkId, block_deviation: u64 },
NetworkTypeUpdated { chain_id: T::NetworkId, network_type: NetworkType },
NetworkCurveUpdated { chain_id: T::NetworkId, network_curve: NetworkCurve },
NetworkDecimalsUpdated { chain_id: T::NetworkId, decimals: u8 },
NetworkGatekeeperUpdated { chain_id: T::NetworkId },
NetworkIncomingShareUpdated { chain_id: T::NetworkId, incoming_share: u32 },
NetworkOutgoingShareUpdated { chain_id: T::NetworkId, outgoing_share: u32 },
NetworkAvgBlockSpeedUpdated { chain_id: T::NetworkId, avg_block_speed: u64 },
NetworkRemoved { chain_id: T::NetworkId },
}
#[pallet::storage]
#[pallet::getter(fn network_imbalance)]
pub type NetworkImbalance<T: Config> = StorageValue<
_,
NetworkImbalanceState<BalanceOf<T>>,
ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn network_indexes)]
pub type NetworkIndexes<T: Config> =
StorageValue<_, BoundedVec<T::NetworkId, T::MaxNetworks>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn network_curves)]
pub type NetworkCurves<T: Config> = StorageMap<
_,
Twox64Concat, NetworkCurve,
BoundedBTreeMap<NetworkType, u32, T::MaxNetworks>,
ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn network_curves_vec)]
pub type NetworkCurvesVec<T: Config> =
StorageValue<_, BoundedVec<NetworkCurve, T::MaxNetworks>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn networks)]
pub type Networks<T: Config> = StorageMap<
_,
Twox64Concat, T::NetworkId,
NetworkData,
OptionQuery,
>;
#[pallet::storage]
#[pallet::getter(fn gatekeeper_amounts)]
pub type GatekeeperAmounts<T: Config> =
StorageMap<_, Twox64Concat, T::NetworkId, BalanceOf<T>, ValueQuery>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub networks: Vec<NetworkInitiation<T::NetworkId, BalanceOf<T>>>,
}
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { networks: sp_std::vec![] }
}
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
self.networks
.iter()
.for_each(|network| {
Pallet::<T>::do_register_network(network.id, network.data.clone())
.expect("Error registering network");
GatekeeperAmounts::<T>::insert(network.id, network.amount);
});
}
}
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::register_network(
network.gatekeeper.len() as u32,
network.selector.len() as u32,
network.default_endpoints
.iter()
.map(|endpoint| endpoint.len())
.max()
.unwrap_or_default() 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_selector())]
pub fn update_network_selector(
origin: OriginFor<T>,
chain_id: T::NetworkId,
selector: BoundedVec<u8, ConstU32<MAX_SELECTOR_LEN>>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_nework_selector(chain_id, selector)
}
#[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<BoundedVec<u8, ConstU32<MAX_ENDPOINT_LEN>>>,
) -> 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_deviation())]
pub fn update_network_block_deviation(
origin: OriginFor<T>,
chain_id: T::NetworkId,
block_deviation: u64,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_block_deviation(chain_id, block_deviation)
}
#[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_curve())]
pub fn update_network_curve(
origin: OriginFor<T>,
chain_id: T::NetworkId,
network_curve: NetworkCurve,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_curve(chain_id, network_curve)
}
#[pallet::call_index(8)]
#[pallet::weight(T::WeightInfo::update_network_gatekeeper())]
pub fn update_network_gatekeeper(
origin: OriginFor<T>,
chain_id: T::NetworkId,
gatekeeper: BoundedVec<u8, ConstU32<MAX_GATEKEEPER_LEN>>,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_gatekeeper(chain_id, gatekeeper)
}
#[pallet::call_index(9)]
#[pallet::weight(T::WeightInfo::update_incoming_network_share())]
pub fn update_incoming_network_share(
origin: OriginFor<T>,
chain_id: T::NetworkId,
incoming_share: u32,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_incoming_network_share(chain_id, incoming_share)
}
#[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::update_outgoing_network_share())]
pub fn update_outgoing_network_share(
origin: OriginFor<T>,
chain_id: T::NetworkId,
outgoing_share: u32,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_outgoing_network_share(chain_id, outgoing_share)
}
#[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)
}
#[pallet::call_index(12)]
#[pallet::weight(T::WeightInfo::update_network_decimals())]
pub fn update_network_decimals(
origin: OriginFor<T>,
chain_id: T::NetworkId,
decimals: u8,
) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_network_decimals(chain_id, decimals)
}
}
}
impl<T: Config> Pallet<T> {
/// Register a new network.
pub fn do_register_network(
chain_id: T::NetworkId,
network: NetworkData,
) -> DispatchResult {
let network_curve = network.curve;
let network_type = network.r#type;
ensure!(
!Networks::<T>::contains_key(&chain_id),
Error::<T>::NetworkAlreadyRegistered,
);
let mut modified_indexes = NetworkIndexes::<T>::get();
modified_indexes.try_push(chain_id.clone())
.map_err(|_| Error::<T>::TooManyNetworks)?;
let mut modified_curves_map = NetworkCurves::<T>::get(network_curve);
if let Some(counter) = modified_curves_map.get_mut(&network_type) {
*counter = counter.saturating_add(1);
} else {
modified_curves_map.try_insert(network_type, 1u32)
.map_err(|_| Error::<T>::TooManyNetworks)?;
}
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
if !modified_curves_vec.contains(&network_curve) {
modified_curves_vec.try_push(network_curve)
.map_err(|_| Error::<T>::TooManyNetworks)?;
}
Networks::<T>::insert(&chain_id, network);
NetworkIndexes::<T>::put(modified_indexes);
NetworkCurves::<T>::insert(network_curve, modified_curves_map);
NetworkCurvesVec::<T>::put(modified_curves_vec);
Self::deposit_event(Event::<T>::NetworkRegistered { chain_id });
Ok(())
}
/// Remove existent network.
pub fn do_remove_network(chain_id: T::NetworkId) -> DispatchResult {
let network = Networks::<T>::get(&chain_id)
.ok_or(Error::<T>::NetworkDoesNotExist)?;
let network_curve = network.curve;
let network_type = network.r#type;
let mut modified_curves_map = NetworkCurves::<T>::get(network_curve);
let counter = modified_curves_map
.get_mut(&network_type)
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
*counter = counter.saturating_sub(1);
let mut should_remove_curve_from_vec = false;
if *counter == 0 {
modified_curves_map.remove(&network_type);
if modified_curves_map.is_empty() {
should_remove_curve_from_vec = true;
}
}
let mut modified_indexes = NetworkIndexes::<T>::get();
modified_indexes.retain(|id| id != &chain_id);
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
if should_remove_curve_from_vec {
modified_curves_vec.retain(|curve| curve != &network_curve);
}
Networks::<T>::remove(&chain_id);
NetworkIndexes::<T>::put(modified_indexes);
NetworkCurvesVec::<T>::put(modified_curves_vec);
if modified_curves_map.is_empty() {
NetworkCurves::<T>::remove(network_curve);
} else {
NetworkCurves::<T>::insert(network_curve, modified_curves_map);
}
Self::deposit_event(Event::<T>::NetworkRemoved { chain_id });
Ok(())
}
/// Update existent network name.
pub fn do_update_nework_selector(
chain_id: T::NetworkId,
selector: BoundedVec<u8, ConstU32<MAX_SELECTOR_LEN>>,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(selector.len() == 4, Error::<T>::InvalidSelectorLen);
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
network.selector = selector;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkSelectorUpdated { chain_id });
Ok(())
}
/// Update existent network default endpoint.
pub fn do_update_network_endpoint(
chain_id: T::NetworkId,
maybe_index: Option<u32>,
maybe_endpoint: Option<BoundedVec<u8, ConstU32<MAX_ENDPOINT_LEN>>>,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
match (maybe_index, maybe_endpoint) {
(Some(index), Some(endpoint)) => {
let idx = index as usize;
ensure!(idx < network.default_endpoints.len(), Error::<T>::IndexOutOfBounds);
let _ = core::mem::replace(&mut network.default_endpoints[idx], endpoint);
Self::deposit_event(Event::<T>::NetworkEndpointUpdated { chain_id, index });
}
(None, Some(endpoint)) => {
network.default_endpoints.try_push(endpoint).map_err(|_| Error::<T>::TooManyEndpoints)?;
Self::deposit_event(Event::<T>::NetworkEndpointAdded { chain_id });
}
(Some(index), None) => {
let idx = index as usize;
ensure!(idx < network.default_endpoints.len(), Error::<T>::IndexOutOfBounds);
network.default_endpoints.remove(idx);
Self::deposit_event(Event::<T>::NetworkEndpointRemoved { chain_id, index });
}
(None, None) => {}
}
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 block deviation between blocks.
pub fn do_update_network_block_deviation(
chain_id: T::NetworkId,
block_deviation: u64,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
network.block_deviation = block_deviation;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkBlockDeviationUpdated {
chain_id,
block_deviation,
});
Ok(())
}
/// Update existent network decimals.
pub fn do_update_network_decimals(
chain_id: T::NetworkId,
decimals: u8,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
network.decimals = decimals;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkDecimalsUpdated {
chain_id,
decimals,
});
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 {
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
network.r#type = network_type;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkTypeUpdated {
chain_id,
network_type,
});
Ok(())
}
/// Update underlying network curve.
pub fn do_update_network_curve(
chain_id: T::NetworkId,
network_curve: NetworkCurve,
) -> DispatchResult {
let mut network = Networks::<T>::get(&chain_id)
.ok_or(Error::<T>::NetworkDoesNotExist)?;
let prev_curve = network.curve;
let network_type = network.r#type;
if prev_curve == network_curve {
return Ok(());
}
let mut modified_prev_map = NetworkCurves::<T>::get(prev_curve);
let counter = modified_prev_map
.get_mut(&network_type)
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
*counter = counter.saturating_sub(1);
let mut should_remove_prev_from_vec = false;
if *counter == 0 {
modified_prev_map.remove(&network_type);
if modified_prev_map.is_empty() {
should_remove_prev_from_vec = true;
}
}
let mut modified_curr_map = NetworkCurves::<T>::get(network_curve);
if let Some(counter) = modified_curr_map.get_mut(&network_type) {
*counter = counter.saturating_add(1);
} else {
modified_curr_map.try_insert(network_type, 1u32)
.map_err(|_| Error::<T>::TooManyNetworks)?;
}
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
if should_remove_prev_from_vec {
modified_curves_vec.retain(|curve| curve != &prev_curve);
}
if !modified_curves_vec.contains(&network_curve) {
modified_curves_vec.try_push(network_curve)
.map_err(|_| Error::<T>::TooManyNetworks)?;
}
network.curve = network_curve;
Networks::<T>::insert(&chain_id, network);
NetworkCurves::<T>::insert(network_curve, modified_curr_map);
NetworkCurvesVec::<T>::put(modified_curves_vec);
if modified_prev_map.is_empty() {
NetworkCurves::<T>::remove(prev_curve);
} else {
NetworkCurves::<T>::insert(prev_curve, modified_prev_map);
}
Self::deposit_event(Event::<T>::NetworkCurveUpdated {
chain_id,
network_curve,
});
Ok(())
}
/// Update existent network gatekeeper.
pub fn do_update_network_gatekeeper(
chain_id: T::NetworkId,
gatekeeper: BoundedVec<u8, ConstU32<MAX_GATEKEEPER_LEN>>,
) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
network.gatekeeper = gatekeeper;
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkGatekeeperUpdated { chain_id });
Ok(())
}
pub fn do_update_incoming_network_share(
chain_id: T::NetworkId,
incoming_share: 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_share = incoming_share;
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkIncomingShareUpdated {
chain_id,
incoming_share,
});
Ok(())
}
pub fn do_update_outgoing_network_share(
chain_id: T::NetworkId,
outgoing_share: 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_share = outgoing_share;
*maybe_network = Some(net.clone());
Ok(())
})?;
Self::deposit_event(Event::<T>::NetworkOutgoingShareUpdated {
chain_id,
outgoing_share,
});
Ok(())
}
}
impl<T: Config> NetworkDataBasicHandler for Pallet<T> {
type NetworkId = T::NetworkId;
type NetworkType = NetworkType;
type NetworkCurve = NetworkCurve;
}
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
fn count() -> u32 {
NetworkIndexes::<T>::decode_len()
.map(|len| len as u32)
.unwrap_or_default()
}
fn contains_key(n: &Self::NetworkId) -> bool {
Networks::<T>::contains_key(n)
}
fn curve_exists(curve: &Self::NetworkCurve) -> bool {
NetworkCurves::<T>::contains_key(curve)
}
fn get(n: &Self::NetworkId) -> Option<NetworkData> {
Networks::<T>::get(n)
}
fn network_for_block(block_number: impl Into<usize>) -> Option<(Self::NetworkId, NetworkData)> {
let network_indexes = NetworkIndexes::<T>::get();
block_number
.into()
.checked_rem(network_indexes.len())
.map(|id| {
network_indexes.get(id).copied().and_then(|network_id| {
Self::get(&network_id).map(|network_data| (network_id, network_data))
})
})
.flatten()
}
fn iter() -> PrefixIterator<(Self::NetworkId, NetworkData)> {
Networks::<T>::iter()
}
fn iter_indexes() -> impl Iterator<Item = Self::NetworkId> {
NetworkIndexes::<T>::get().into_iter()
}
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve> {
NetworkCurvesVec::<T>::get().into_iter()
}
fn iter_types_by_curve(
curve: &Self::NetworkCurve
) -> impl Iterator<Item = Self::NetworkType> {
NetworkCurves::<T>::get(curve)
.into_iter()
.map(|(network_type, _)| network_type)
}
}
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 register_incoming(
network_id: &T::NetworkId,
amount: BalanceOf<T>,
) -> Result<BalanceOf<T>, ()> {
let incoming_share = Networks::<T>::get(&network_id)
.map(|network| network.incoming_share)
.ok_or(())?;
GatekeeperAmounts::<T>::try_mutate(network_id, |gatekeeper_amount| -> Result<(), ()> {
*gatekeeper_amount = gatekeeper_amount.checked_add(&amount).ok_or(())?;
Ok(())
})?;
let curve_share = Perbill::from_parts(incoming_share).mul_ceil(amount);
let final_amount = amount.saturating_sub(curve_share);
NetworkImbalance::<T>::try_mutate(|imbalance_state| -> Result<(), ()> {
imbalance_state.incoming = imbalance_state.incoming
.checked_add(&final_amount)
.ok_or(())?;
imbalance_state.curve_share = imbalance_state.curve_share
.checked_add(&curve_share)
.ok_or(())?;
Ok(())
})?;
Ok(final_amount)
}
fn register_outgoing(
network_id: &T::NetworkId,
amount: BalanceOf<T>
) -> Result<BalanceOf<T>, ()> {
let outgoing_share = Networks::<T>::get(&network_id)
.map(|network| network.outgoing_share)
.ok_or(())?;
GatekeeperAmounts::<T>::try_mutate(network_id, |gatekeeper_amount| -> Result<(), ()> {
*gatekeeper_amount = gatekeeper_amount.checked_sub(&amount).ok_or(())?;
Ok(())
})?;
let curve_share = Perbill::from_parts(outgoing_share).mul_ceil(amount);
let final_amount = amount.saturating_sub(curve_share);
NetworkImbalance::<T>::try_mutate(|imbalance_state| -> Result<(), ()> {
imbalance_state.outgoing = imbalance_state.outgoing
.checked_add(&final_amount)
.ok_or(())?;
imbalance_state.curve_share = imbalance_state.curve_share
.checked_add(&curve_share)
.ok_or(())?;
Ok(())
})?;
Ok(final_amount)
}
}