@@ -2,8 +2,16 @@ use super::*;
22use alloc:: collections:: BTreeMap ;
33use safe_math:: * ;
44use substrate_fixed:: types:: U96F32 ;
5+ use frame_support:: traits:: {
6+ Imbalance ,
7+ tokens:: {
8+ Precision , Preservation ,
9+ fungible:: { Balanced , Inspect , Mutate } ,
10+ } ,
11+ } ;
512use subtensor_runtime_common:: { AlphaCurrency , Currency , NetUid , TaoCurrency } ;
613use subtensor_swap_interface:: SwapHandler ;
14+ use frame_support:: traits:: tokens:: imbalance:: Credit ;
715
816// Distribute dividends to each hotkey
917macro_rules! asfloat {
@@ -43,8 +51,11 @@ impl<T: Config> Pallet<T> {
4351 let root_sell_flag = Self :: get_network_root_sell_flag ( & subnets_to_emit_to) ;
4452 log:: debug!( "Root sell flag: {root_sell_flag:?}" ) ;
4553
46- // --- 4. Emit to subnets for this block.
47- Self :: emit_to_subnets ( & subnets_to_emit_to, & subnet_emissions, root_sell_flag) ;
54+ // --- 4. Mint emission and emit to subnets for this block.
55+ // We mint the emission here using the Imbalance trait to ensure conservation.
56+ let emission_u64: u64 = block_emission. saturating_to_num :: < u64 > ( ) ;
57+ let imbalance = T :: Currency :: issue ( emission_u64) ;
58+ Self :: emit_to_subnets ( & subnets_to_emit_to, & subnet_emissions, root_sell_flag, imbalance) ;
4859
4960 // --- 5. Drain pending emissions.
5061 let emissions_to_distribute = Self :: drain_pending ( & subnets, current_block) ;
@@ -101,6 +112,77 @@ impl<T: Config> Pallet<T> {
101112 * total = total. saturating_add ( injected_tao) ;
102113 } ) ;
103114
115+ pub fn inject_and_maybe_swap (
116+ subnets_to_emit_to : & [ NetUid ] ,
117+ tao_in : & BTreeMap < NetUid , U96F32 > ,
118+ alpha_in : & BTreeMap < NetUid , U96F32 > ,
119+ excess_tao : & BTreeMap < NetUid , U96F32 > ,
120+ mut imbalance : Credit < T :: AccountId , T :: Currency > ,
121+ ) {
122+ for netuid_i in subnets_to_emit_to. iter ( ) {
123+ let tao_in_i: TaoCurrency =
124+ tou64 ! ( * tao_in. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) . into ( ) ;
125+ let alpha_in_i: AlphaCurrency =
126+ tou64 ! ( * alpha_in. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) . into ( ) ;
127+ let tao_to_swap_with: TaoCurrency =
128+ tou64 ! ( excess_tao. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) . into ( ) ;
129+
130+ // Handle Imbalance Split
131+ // We need to account for both directly injected TAO and TAO used for swapping.
132+ let total_tao_needed = tao_in_i. saturating_add ( tao_to_swap_with) ;
133+ let total_tao_u64: u64 = total_tao_needed. into ( ) ;
134+
135+ // Extract the credit needed for this subnet.
136+ let ( subnet_credit, remaining) = imbalance. split ( total_tao_u64. into ( ) ) ;
137+ imbalance = remaining;
138+
139+ // Burn/Drop the credit to "deposit" it into the virtual staking system.
140+ // This ensures we successfully minted the required amount.
141+ // In a future vault-based system, we would deposit this into a subnet account.
142+ if subnet_credit. peek ( ) < total_tao_u64. into ( ) {
143+ log:: error!(
144+ "CRITICAL: Insufficient emission imbalance for netuid {:?}. Needed: {:?}, Got: {:?}" ,
145+ netuid_i,
146+ total_tao_u64,
147+ subnet_credit. peek( )
148+ ) ;
149+ }
150+ let _ = subnet_credit;
151+
152+ T :: SwapInterface :: adjust_protocol_liquidity ( * netuid_i, tao_in_i, alpha_in_i) ;
153+
154+ if tao_to_swap_with > TaoCurrency :: ZERO {
155+ let buy_swap_result = Self :: swap_tao_for_alpha (
156+ * netuid_i,
157+ tao_to_swap_with,
158+ T :: SwapInterface :: max_price ( ) ,
159+ true ,
160+ ) ;
161+ if let Ok ( buy_swap_result_ok) = buy_swap_result {
162+ let bought_alpha: AlphaCurrency = buy_swap_result_ok. amount_paid_out . into ( ) ;
163+ Self :: recycle_subnet_alpha ( * netuid_i, bought_alpha) ;
164+ }
165+ }
166+
167+ // Inject Alpha in.
168+ let alpha_in_i =
169+ AlphaCurrency :: from ( tou64 ! ( * alpha_in. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) ) ;
170+ SubnetAlphaInEmission :: < T > :: insert ( * netuid_i, alpha_in_i) ;
171+ SubnetAlphaIn :: < T > :: mutate ( * netuid_i, |total| {
172+ * total = total. saturating_add ( alpha_in_i) ;
173+ } ) ;
174+
175+ // Inject TAO in.
176+ let injected_tao: TaoCurrency =
177+ tou64 ! ( * tao_in. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) . into ( ) ;
178+ SubnetTaoInEmission :: < T > :: insert ( * netuid_i, injected_tao) ;
179+ SubnetTAO :: < T > :: mutate ( * netuid_i, |total| {
180+ * total = total. saturating_add ( injected_tao) ;
181+ } ) ;
182+ TotalStake :: < T > :: mutate ( |total| {
183+ * total = total. saturating_add ( injected_tao) ;
184+ } ) ;
185+
104186 // Update total TAO issuance.
105187 let difference_tao = tou64 ! ( * excess_tao. get( netuid_i) . unwrap_or( & asfloat!( 0 ) ) ) ;
106188 TotalIssuance :: < T > :: mutate ( |total| {
@@ -168,6 +250,7 @@ impl<T: Config> Pallet<T> {
168250 subnets_to_emit_to : & [ NetUid ] ,
169251 subnet_emissions : & BTreeMap < NetUid , U96F32 > ,
170252 root_sell_flag : bool ,
253+ mut imbalance : Credit < T :: AccountId , T :: Currency > ,
171254 ) {
172255 // --- 1. Get subnet terms (tao_in, alpha_in, and alpha_out)
173256 // and excess_tao amounts.
@@ -179,10 +262,17 @@ impl<T: Config> Pallet<T> {
179262 log:: debug!( "excess_amount: {excess_amount:?}" ) ;
180263
181264 // --- 2. Inject TAO and ALPHA to pool and swap with excess TAO.
182- Self :: inject_and_maybe_swap ( subnets_to_emit_to, & tao_in, & alpha_in, & excess_amount) ;
265+ Self :: inject_and_maybe_swap (
266+ subnets_to_emit_to,
267+ & tao_in,
268+ & alpha_in,
269+ & excess_amount,
270+ imbalance,
271+ ) ;
183272
184273 // --- 3. Inject ALPHA for participants.
185274 let cut_percent: U96F32 = Self :: get_float_subnet_owner_cut ( ) ;
275+ // ... (rest of logic) ...
186276
187277 // Get total TAO on root.
188278 let root_tao: U96F32 = asfloat ! ( SubnetTAO :: <T >:: get( NetUid :: ROOT ) ) ;
0 commit comments