701 lines
23 KiB
Rust
701 lines
23 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::{
|
|
traits::{CheckedSub, CheckedAdd, AtLeast32BitUnsigned, Member},
|
|
curve::PiecewiseLinear,
|
|
DispatchResult,
|
|
};
|
|
use sp_std::{prelude::*, convert::TryInto};
|
|
|
|
pub use ghost_traits::networks::{
|
|
NetworkDataBasicHandler, NetworkDataInspectHandler,
|
|
NetworkDataMutateHandler,
|
|
};
|
|
|
|
mod weights;
|
|
|
|
pub use module::*;
|
|
pub use crate::weights::WeightInfo;
|
|
|
|
#[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_endpoint: Vec<u8>,
|
|
pub gatekeeper: Vec<u8>,
|
|
pub topic_name: Vec<u8>,
|
|
pub finality_delay: Option<u64>,
|
|
pub release_delay: Option<u64>,
|
|
pub network_type: NetworkType,
|
|
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, default_endpoint: Vec<u8> },
|
|
NetworkFinalityDelayUpdated { chain_id: T::NetworkId, finality_delay: Option<u64> },
|
|
NetworkReleaseDelayUpdated { chain_id: T::NetworkId, release_delay: Option<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_endpoint.len() 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(
|
|
default_endpoint.len() as u32
|
|
))]
|
|
pub fn update_network_endpoint(
|
|
origin: OriginFor<T>,
|
|
chain_id: T::NetworkId,
|
|
default_endpoint: Vec<u8>,
|
|
) -> DispatchResult {
|
|
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
|
Self::do_update_network_endpoint(
|
|
chain_id,
|
|
default_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: Option<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_release_delay())]
|
|
pub fn update_network_release_delay(
|
|
origin: OriginFor<T>,
|
|
chain_id: T::NetworkId,
|
|
release_delay: Option<u64>,
|
|
) -> DispatchResult {
|
|
T::UpdateOrigin::ensure_origin_or_root(origin)?;
|
|
Self::do_update_network_release_delay(
|
|
chain_id,
|
|
release_delay,
|
|
)
|
|
}
|
|
|
|
#[pallet::call_index(5)]
|
|
#[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(6)]
|
|
#[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(7)]
|
|
#[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(8)]
|
|
#[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(9)]
|
|
#[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(10)]
|
|
#[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,
|
|
default_endpoint: 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.default_endpoint = default_endpoint.clone();
|
|
*maybe_network = Some(net.clone());
|
|
Ok(())
|
|
})?;
|
|
Self::deposit_event(Event::<T>::NetworkEndpointUpdated {
|
|
chain_id,
|
|
default_endpoint,
|
|
});
|
|
Ok(())
|
|
}
|
|
|
|
/// Update existent network default endpoint.
|
|
pub fn do_update_network_finality_delay(
|
|
chain_id: T::NetworkId,
|
|
finality_delay: Option<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 endpoint.
|
|
pub fn do_update_network_release_delay(
|
|
chain_id: T::NetworkId,
|
|
release_delay: Option<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.release_delay = release_delay;
|
|
*maybe_network = Some(net.clone());
|
|
Ok(())
|
|
})?;
|
|
Self::deposit_event(Event::<T>::NetworkReleaseDelayUpdated {
|
|
chain_id,
|
|
release_delay,
|
|
});
|
|
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>, 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(())
|
|
}
|
|
})?;
|
|
|
|
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, new_bridged_in_amount))
|
|
}
|
|
|
|
fn decrease_gatekeeper_amount(
|
|
network_id: &T::NetworkId,
|
|
amount: &BalanceOf<T>,
|
|
) -> Result<(BalanceOf<T>, 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(())
|
|
}
|
|
})?;
|
|
|
|
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_gatekeeper_amount, new_bridged_out_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());
|
|
}
|
|
}
|