@@ -1203,4 +1203,45 @@ mod tests {
12031203 assert_abs_diff_eq ! ( actual, expected, epsilon = epsilon) ;
12041204 } ) ;
12051205 }
1206+
1207+ /// This is a real-life scenario test when someone lost 7 TAO on Chutes (SN64)
1208+ /// when paying fees in Alpha. The scenario occured because the update of share value
1209+ /// of one coldkey (update_value_for_one) hit the scenario of full unstake.
1210+ ///
1211+ /// Specifically, the following condition was triggered:
1212+ ///
1213+ /// `(shared_value + 2_628_000_000_000_000_u64).checked_div(new_denominator)`
1214+ ///
1215+ /// returned None because new_denominator was too low and division of
1216+ /// `shared_value + 2_628_000_000_000_000_u64` by new_denominator has overflown U64F64.
1217+ ///
1218+ /// This test fails on the old version of share pool (with much lower tolerances).
1219+ ///
1220+ /// cargo test --package share-pool --lib -- tests::test_loss_due_to_precision --exact --nocapture
1221+ #[ test]
1222+ fn test_loss_due_to_precision ( ) {
1223+ let mock_ops = MockSharePoolDataOperations :: new ( ) ;
1224+ let mut pool = SharePool :: < u16 , MockSharePoolDataOperations > :: new ( mock_ops) ;
1225+
1226+ // Setup pool so that initial coldkey's alpha is 10% of 1e12 = 1e11 rao.
1227+ let low_denominator = SafeFloat :: new ( SafeInt :: from ( 1 ) , -14 ) . unwrap ( ) ;
1228+ let low_share = SafeFloat :: new ( SafeInt :: from ( 1 ) , -15 ) . unwrap ( ) ;
1229+ pool. state_ops . set_denominator ( low_denominator) ;
1230+ pool. state_ops . set_shared_value ( 1_000_000_000_000_u64 ) ;
1231+ pool. state_ops . set_share ( & 1 , low_share) ;
1232+
1233+ let value_before = pool. get_value ( & 1 ) as i128 ;
1234+ assert_abs_diff_eq ! ( value_before as f64 , 100_000_000_000. , epsilon = 0.1 ) ;
1235+
1236+ // Remove a little stake
1237+ let unstake_amount = 1000i64 ;
1238+ pool. update_value_for_one ( & 1 , unstake_amount. neg ( ) ) ;
1239+
1240+ let value_after = pool. get_value ( & 1 ) as i128 ;
1241+ assert_abs_diff_eq ! (
1242+ ( value_before - value_after) as f64 ,
1243+ unstake_amount as f64 ,
1244+ epsilon = unstake_amount as f64 / 1_000_000_000.
1245+ ) ;
1246+ }
12061247}
0 commit comments