fc_pallet_black_hole/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
2
3extern crate alloc;
9
10use alloc::boxed::Box;
11use frame::prelude::*;
12use fungible::{Inspect, Mutate};
13
14#[cfg(feature = "runtime-benchmarks")]
15pub mod benchmarking;
16
17#[cfg(test)]
18mod mock;
19#[cfg(test)]
20mod tests;
21
22pub mod weights;
23pub use weights::*;
24
25pub use pallet::*;
26
27#[frame::pallet]
28pub mod pallet {
29 use super::*;
30 use frame::traits::{Block, Header};
31
32 pub(crate) type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
33 pub(crate) type BalanceOf<T> = <<T as Config>::Balances as Inspect<AccountIdOf<T>>>::Balance;
34 pub(crate) type SystemBlockNumberFor<T> =
35 <<<T as frame_system::Config>::Block as Block>::Header as Header>::Number;
36 pub(crate) type BlockNumberFor<T> =
37 <<T as Config>::BlockNumberProvider as BlockNumberProvider>::BlockNumber;
38
39 #[pallet::config]
40 pub trait Config: frame_system::Config {
41 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
45 type WeightInfo: WeightInfo;
47
48 type EventHorizonDispatchOrigin: EnsureOrigin<Self::RuntimeOrigin>;
54
55 type Balances: Mutate<Self::AccountId>;
59 type BlockNumberProvider: BlockNumberProvider;
61
62 #[pallet::constant]
66 type PalletId: Get<PalletId>;
67 #[pallet::constant]
70 type BurnPeriod: Get<BlockNumberFor<Self>>;
71 }
72
73 #[pallet::storage]
75 pub type LastBurn<T> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
76 #[pallet::storage]
78 pub type BlackHoleMass<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
79
80 #[pallet::pallet]
81 pub struct Pallet<T>(_);
82
83 #[pallet::event]
84 #[pallet::generate_deposit(pub(super) fn deposit_event)]
85 pub enum Event<T: Config> {
86 BalanceBurned,
87 }
88
89 #[pallet::hooks]
90 impl<T: Config> Hooks<SystemBlockNumberFor<T>> for Pallet<T> {
91 fn on_idle(_: SystemBlockNumberFor<T>, remaining_weight: Weight) -> Weight {
92 if remaining_weight.all_lt(T::WeightInfo::burn()) {
93 return Zero::zero();
94 }
95 Self::burn()
96 }
97 }
98
99 #[pallet::call]
100 impl<T: Config> Pallet<T> {
101 #[pallet::call_index(0)]
102 #[pallet::weight({
103 let di = call.get_dispatch_info();
104 let weight = T::WeightInfo::dispatch_as_event_horizon()
105 .saturating_add(T::DbWeight::get().reads_writes(1, 1))
106 .saturating_add(di.call_weight);
107 (weight, di.class)
108 })]
109 pub fn dispatch_as_event_horizon(
110 origin: OriginFor<T>,
111 call: Box<T::RuntimeCall>,
112 ) -> DispatchResult {
113 T::EventHorizonDispatchOrigin::ensure_origin(origin)?;
114 Self::do_initialize();
115
116 call.dispatch(frame_system::RawOrigin::Signed(Self::event_horizon()).into())
117 .map(|_| ())
118 .map_err(|e| e.error)
119 }
120 }
121
122 impl<T: Config> Pallet<T> {
123 pub fn event_horizon() -> T::AccountId {
124 T::PalletId::get().into_account_truncating()
125 }
126
127 #[inline]
128 fn do_initialize() {
129 if !frame_system::Pallet::<T>::account_exists(&Self::event_horizon()) {
130 frame_system::Pallet::<T>::inc_providers(&Self::event_horizon());
131 }
132 }
133
134 pub(crate) fn burn() -> Weight {
135 if LastBurn::<T>::get().le(&T::BlockNumberProvider::current_block_number()
136 .saturating_sub(T::BurnPeriod::get()))
137 {
138 let burn_account = Self::event_horizon();
139 let burn_balance = T::Balances::total_balance(&burn_account);
140
141 let _ = T::Balances::burn_from(
143 &burn_account,
144 burn_balance,
145 Preservation::Expendable,
146 Precision::Exact,
147 Fortitude::Force,
148 );
149
150 BlackHoleMass::<T>::set(BlackHoleMass::<T>::get().saturating_add(burn_balance));
151 LastBurn::<T>::set(T::BlockNumberProvider::current_block_number());
152 Self::deposit_event(Event::<T>::BalanceBurned);
153 }
154
155 T::WeightInfo::burn()
156 }
157 }
158}