@@ -2928,3 +2928,353 @@ fn test_zero_shares_zero_emission() {
29282928 assert_eq ! ( SubnetAlphaIn :: <Test >:: get( netuid2) , initial. into( ) ) ;
29292929 } ) ;
29302930}
2931+
2932+ #[ test]
2933+ fn test_mining_emission_distribution_with_subsidy ( ) {
2934+ new_test_ext ( 1 ) . execute_with ( || {
2935+ let validator_coldkey = U256 :: from ( 1 ) ;
2936+ let validator_hotkey = U256 :: from ( 2 ) ;
2937+ let validator_miner_coldkey = U256 :: from ( 3 ) ;
2938+ let validator_miner_hotkey = U256 :: from ( 4 ) ;
2939+ let miner_coldkey = U256 :: from ( 5 ) ;
2940+ let miner_hotkey = U256 :: from ( 6 ) ;
2941+ let netuid = NetUid :: from ( 1 ) ;
2942+ let subnet_tempo = 10 ;
2943+ let stake: u64 = 100_000_000_000 ;
2944+ let root_stake: u64 = 200_000_000_000 ; // 200 TAO
2945+
2946+ // Create root network
2947+ SubtensorModule :: set_tao_weight ( 0 ) ; // Start tao weight at 0
2948+ SubtokenEnabled :: < Test > :: insert ( NetUid :: ROOT , true ) ;
2949+ NetworksAdded :: < Test > :: insert ( NetUid :: ROOT , true ) ;
2950+
2951+ // Add network, register hotkeys, and setup network parameters
2952+ add_network ( netuid, subnet_tempo, 0 ) ;
2953+ SubnetMechanism :: < Test > :: insert ( netuid, 1 ) ; // Set mechanism to 1
2954+
2955+ // Setup large LPs to prevent slippage
2956+ SubnetTAO :: < Test > :: insert ( netuid, TaoCurrency :: from ( 1_000_000_000_000_000 ) ) ;
2957+ SubnetAlphaIn :: < Test > :: insert ( netuid, AlphaCurrency :: from ( 1_000_000_000_000_000 ) ) ;
2958+
2959+ register_ok_neuron ( netuid, validator_hotkey, validator_coldkey, 0 ) ;
2960+ register_ok_neuron ( netuid, validator_miner_hotkey, validator_miner_coldkey, 1 ) ;
2961+ register_ok_neuron ( netuid, miner_hotkey, miner_coldkey, 2 ) ;
2962+ SubtensorModule :: add_balance_to_coldkey_account (
2963+ & validator_coldkey,
2964+ stake + ExistentialDeposit :: get ( ) ,
2965+ ) ;
2966+ SubtensorModule :: add_balance_to_coldkey_account (
2967+ & validator_miner_coldkey,
2968+ stake + ExistentialDeposit :: get ( ) ,
2969+ ) ;
2970+ SubtensorModule :: add_balance_to_coldkey_account (
2971+ & miner_coldkey,
2972+ stake + ExistentialDeposit :: get ( ) ,
2973+ ) ;
2974+ SubtensorModule :: set_weights_set_rate_limit ( netuid, 0 ) ;
2975+ step_block ( subnet_tempo) ;
2976+ SubnetOwnerCut :: < Test > :: set ( u16:: MAX / 10 ) ;
2977+ // There are two validators and three neurons
2978+ MaxAllowedUids :: < Test > :: set ( netuid, 3 ) ;
2979+ SubtensorModule :: set_max_allowed_validators ( netuid, 2 ) ;
2980+
2981+ // Setup stakes:
2982+ // Stake from validator
2983+ // Stake from valiminer
2984+ assert_ok ! ( SubtensorModule :: add_stake(
2985+ RuntimeOrigin :: signed( validator_coldkey) ,
2986+ validator_hotkey,
2987+ netuid,
2988+ stake. into( )
2989+ ) ) ;
2990+ assert_ok ! ( SubtensorModule :: add_stake(
2991+ RuntimeOrigin :: signed( validator_miner_coldkey) ,
2992+ validator_miner_hotkey,
2993+ netuid,
2994+ stake. into( )
2995+ ) ) ;
2996+
2997+ // Setup YUMA so that it creates emissions
2998+ Weights :: < Test > :: insert ( NetUidStorageIndex :: from ( netuid) , 0 , vec ! [ ( 1 , 0xFFFF ) ] ) ;
2999+ Weights :: < Test > :: insert ( NetUidStorageIndex :: from ( netuid) , 1 , vec ! [ ( 2 , 0xFFFF ) ] ) ;
3000+ BlockAtRegistration :: < Test > :: set ( netuid, 0 , 1 ) ;
3001+ BlockAtRegistration :: < Test > :: set ( netuid, 1 , 1 ) ;
3002+ BlockAtRegistration :: < Test > :: set ( netuid, 2 , 1 ) ;
3003+ LastUpdate :: < Test > :: set ( NetUidStorageIndex :: from ( netuid) , vec ! [ 2 , 2 , 2 ] ) ;
3004+ Kappa :: < Test > :: set ( netuid, u16:: MAX / 5 ) ;
3005+ ActivityCutoff :: < Test > :: set ( netuid, u16:: MAX ) ; // makes all stake active
3006+ ValidatorPermit :: < Test > :: insert ( netuid, vec ! [ true , true , false ] ) ;
3007+
3008+ // Run run_coinbase until emissions are drained
3009+ step_block ( subnet_tempo) ;
3010+
3011+ // Add stake to validator so it has root stake
3012+ SubtensorModule :: add_balance_to_coldkey_account ( & validator_coldkey, root_stake. into ( ) ) ;
3013+ // init root
3014+ assert_ok ! ( SubtensorModule :: add_stake(
3015+ RuntimeOrigin :: signed( validator_coldkey) ,
3016+ validator_hotkey,
3017+ NetUid :: ROOT ,
3018+ root_stake. into( )
3019+ ) ) ;
3020+ // Set tao weight non zero
3021+ SubtensorModule :: set_tao_weight ( u64:: MAX / 10 ) ;
3022+
3023+ // Make subsidy happen
3024+ // set price very low, e.g. a lot of alpha in
3025+ //SubnetAlphaIn::<Test>::insert(netuid, AlphaCurrency::from(1_000_000_000_000_000));
3026+ pallet_subtensor_swap:: AlphaSqrtPrice :: < Test > :: insert (
3027+ netuid,
3028+ U64F64 :: saturating_from_num ( 0.01 ) ,
3029+ ) ;
3030+
3031+ // Run run_coinbase until emissions are drained
3032+ step_block ( subnet_tempo) ;
3033+
3034+ log:: info!( "is_sub: Running epoch with subsidy" ) ;
3035+
3036+ let old_root_alpha_divs = PendingRootAlphaDivs :: < Test > :: get ( netuid) ;
3037+ let per_block_emission = SubtensorModule :: get_block_emission_for_issuance (
3038+ SubtensorModule :: get_alpha_issuance ( netuid) . into ( ) ,
3039+ )
3040+ . unwrap_or ( 0 ) ;
3041+
3042+ // step by one block
3043+ step_block ( 1 ) ;
3044+ // Verify that root alpha divs
3045+ let new_root_alpha_divs = PendingRootAlphaDivs :: < Test > :: get ( netuid) ;
3046+ // Check that we are indeed being subsidized, i.e. that root alpha divs are NOT increasing
3047+ assert_eq ! (
3048+ new_root_alpha_divs, old_root_alpha_divs,
3049+ "Root alpha divs should not increase"
3050+ ) ;
3051+ // Check root divs are zero
3052+ assert_eq ! (
3053+ new_root_alpha_divs,
3054+ AlphaCurrency :: ZERO ,
3055+ "Root alpha divs should be zero"
3056+ ) ;
3057+ let miner_stake_before_epoch = SubtensorModule :: get_stake_for_hotkey_and_coldkey_on_subnet (
3058+ & miner_hotkey,
3059+ & miner_coldkey,
3060+ netuid,
3061+ ) ;
3062+ // Run again but with some root stake
3063+ step_block ( subnet_tempo - 2 ) ;
3064+ assert_abs_diff_eq ! (
3065+ PendingEmission :: <Test >:: get( netuid) . to_u64( ) ,
3066+ U96F32 :: saturating_from_num( per_block_emission)
3067+ . saturating_mul( U96F32 :: saturating_from_num( subnet_tempo as u64 ) )
3068+ . saturating_mul( U96F32 :: saturating_from_num( 0.90 ) )
3069+ . saturating_to_num:: <u64 >( ) ,
3070+ epsilon = 100_000_u64 . into( )
3071+ ) ;
3072+ step_block ( 1 ) ;
3073+ assert ! (
3074+ BlocksSinceLastStep :: <Test >:: get( netuid) == 0 ,
3075+ "Blocks since last step should be 0"
3076+ ) ;
3077+
3078+ let miner_uid = Uids :: < Test > :: get ( netuid, miner_hotkey) . unwrap_or ( 0 ) ;
3079+ log:: info!( "Miner uid: {miner_uid:?}" ) ;
3080+ let miner_incentive: AlphaCurrency =
3081+ ( * Incentive :: < Test > :: get ( NetUidStorageIndex :: from ( netuid) )
3082+ . get ( miner_uid as usize )
3083+ . expect ( "Miner uid should be present" ) as u64 )
3084+ . into ( ) ;
3085+ log:: info!( "Miner incentive: {miner_incentive:?}" ) ;
3086+
3087+ // Miner emissions
3088+ let miner_emission_1: u64 = SubtensorModule :: get_stake_for_hotkey_and_coldkey_on_subnet (
3089+ & miner_hotkey,
3090+ & miner_coldkey,
3091+ netuid,
3092+ )
3093+ . to_u64 ( )
3094+ - miner_stake_before_epoch. to_u64 ( ) ;
3095+
3096+ assert_abs_diff_eq ! (
3097+ Incentive :: <Test >:: get( NetUidStorageIndex :: from( netuid) )
3098+ . iter( )
3099+ . sum:: <u16 >( ) ,
3100+ u16 :: MAX ,
3101+ epsilon = 10
3102+ ) ;
3103+
3104+ assert_abs_diff_eq ! (
3105+ miner_emission_1,
3106+ U96F32 :: saturating_from_num( miner_incentive)
3107+ . saturating_div( u16 :: MAX . into( ) )
3108+ . saturating_mul( U96F32 :: saturating_from_num( per_block_emission) )
3109+ . saturating_mul( U96F32 :: saturating_from_num( subnet_tempo + 1 ) )
3110+ . saturating_mul( U96F32 :: saturating_from_num( 0.45 ) ) // miner cut
3111+ . saturating_to_num:: <u64 >( ) ,
3112+ epsilon = 1_000_000_u64
3113+ ) ;
3114+ } ) ;
3115+ }
3116+
3117+ // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_mining_emission_distribution_with_no_subsidy --exact --show-output --nocapture
3118+ #[ test]
3119+ fn test_mining_emission_distribution_with_no_subsidy ( ) {
3120+ new_test_ext ( 1 ) . execute_with ( || {
3121+ let validator_coldkey = U256 :: from ( 1 ) ;
3122+ let validator_hotkey = U256 :: from ( 2 ) ;
3123+ let validator_miner_coldkey = U256 :: from ( 3 ) ;
3124+ let validator_miner_hotkey = U256 :: from ( 4 ) ;
3125+ let miner_coldkey = U256 :: from ( 5 ) ;
3126+ let miner_hotkey = U256 :: from ( 6 ) ;
3127+ let netuid = NetUid :: from ( 1 ) ;
3128+ let subnet_tempo = 10 ;
3129+ let stake: u64 = 100_000_000_000 ;
3130+ let root_stake: u64 = 200_000_000_000 ; // 200 TAO
3131+
3132+ // Create root network
3133+ SubtensorModule :: set_tao_weight ( 0 ) ; // Start tao weight at 0
3134+ SubtokenEnabled :: < Test > :: insert ( NetUid :: ROOT , true ) ;
3135+ NetworksAdded :: < Test > :: insert ( NetUid :: ROOT , true ) ;
3136+
3137+ // Add network, register hotkeys, and setup network parameters
3138+ add_network ( netuid, subnet_tempo, 0 ) ;
3139+ SubnetMechanism :: < Test > :: insert ( netuid, 1 ) ; // Set mechanism to 1
3140+
3141+ // Setup large LPs to prevent slippage
3142+ SubnetTAO :: < Test > :: insert ( netuid, TaoCurrency :: from ( 1_000_000_000_000_000 ) ) ;
3143+ SubnetAlphaIn :: < Test > :: insert ( netuid, AlphaCurrency :: from ( 1_000_000_000_000_000 ) ) ;
3144+
3145+ register_ok_neuron ( netuid, validator_hotkey, validator_coldkey, 0 ) ;
3146+ register_ok_neuron ( netuid, validator_miner_hotkey, validator_miner_coldkey, 1 ) ;
3147+ register_ok_neuron ( netuid, miner_hotkey, miner_coldkey, 2 ) ;
3148+ SubtensorModule :: add_balance_to_coldkey_account (
3149+ & validator_coldkey,
3150+ stake + ExistentialDeposit :: get ( ) ,
3151+ ) ;
3152+ SubtensorModule :: add_balance_to_coldkey_account (
3153+ & validator_miner_coldkey,
3154+ stake + ExistentialDeposit :: get ( ) ,
3155+ ) ;
3156+ SubtensorModule :: add_balance_to_coldkey_account (
3157+ & miner_coldkey,
3158+ stake + ExistentialDeposit :: get ( ) ,
3159+ ) ;
3160+ SubtensorModule :: set_weights_set_rate_limit ( netuid, 0 ) ;
3161+ step_block ( subnet_tempo) ;
3162+ SubnetOwnerCut :: < Test > :: set ( u16:: MAX / 10 ) ;
3163+ // There are two validators and three neurons
3164+ MaxAllowedUids :: < Test > :: set ( netuid, 3 ) ;
3165+ SubtensorModule :: set_max_allowed_validators ( netuid, 2 ) ;
3166+
3167+ // Setup stakes:
3168+ // Stake from validator
3169+ // Stake from valiminer
3170+ assert_ok ! ( SubtensorModule :: add_stake(
3171+ RuntimeOrigin :: signed( validator_coldkey) ,
3172+ validator_hotkey,
3173+ netuid,
3174+ stake. into( )
3175+ ) ) ;
3176+ assert_ok ! ( SubtensorModule :: add_stake(
3177+ RuntimeOrigin :: signed( validator_miner_coldkey) ,
3178+ validator_miner_hotkey,
3179+ netuid,
3180+ stake. into( )
3181+ ) ) ;
3182+
3183+ // Setup YUMA so that it creates emissions
3184+ Weights :: < Test > :: insert ( NetUidStorageIndex :: from ( netuid) , 0 , vec ! [ ( 1 , 0xFFFF ) ] ) ;
3185+ Weights :: < Test > :: insert ( NetUidStorageIndex :: from ( netuid) , 1 , vec ! [ ( 2 , 0xFFFF ) ] ) ;
3186+ BlockAtRegistration :: < Test > :: set ( netuid, 0 , 1 ) ;
3187+ BlockAtRegistration :: < Test > :: set ( netuid, 1 , 1 ) ;
3188+ BlockAtRegistration :: < Test > :: set ( netuid, 2 , 1 ) ;
3189+ LastUpdate :: < Test > :: set ( NetUidStorageIndex :: from ( netuid) , vec ! [ 2 , 2 , 2 ] ) ;
3190+ Kappa :: < Test > :: set ( netuid, u16:: MAX / 5 ) ;
3191+ ActivityCutoff :: < Test > :: set ( netuid, u16:: MAX ) ; // makes all stake active
3192+ ValidatorPermit :: < Test > :: insert ( netuid, vec ! [ true , true , false ] ) ;
3193+
3194+ // Run run_coinbase until emissions are drained
3195+ step_block ( subnet_tempo) ;
3196+
3197+ // Add stake to validator so it has root stake
3198+ SubtensorModule :: add_balance_to_coldkey_account ( & validator_coldkey, root_stake. into ( ) ) ;
3199+ // init root
3200+ assert_ok ! ( SubtensorModule :: add_stake(
3201+ RuntimeOrigin :: signed( validator_coldkey) ,
3202+ validator_hotkey,
3203+ NetUid :: ROOT ,
3204+ root_stake. into( )
3205+ ) ) ;
3206+ // Set tao weight non zero
3207+ SubtensorModule :: set_tao_weight ( u64:: MAX / 10 ) ;
3208+
3209+ // Make subsidy not happen
3210+ // set price very high
3211+ // e.g. very little alpha in pool
3212+ //SubnetAlphaIn::<Test>::insert(netuid, AlphaCurrency::from(5));
3213+ pallet_subtensor_swap:: AlphaSqrtPrice :: < Test > :: insert (
3214+ netuid,
3215+ U64F64 :: saturating_from_num ( 10.0 ) ,
3216+ ) ;
3217+
3218+ // Run run_coinbase until emissions are drained
3219+ step_block ( subnet_tempo) ;
3220+
3221+ log:: info!( "is_sub: Running epoch with no subsidy" ) ;
3222+
3223+ let old_root_alpha_divs = PendingRootAlphaDivs :: < Test > :: get ( netuid) ;
3224+ let miner_stake_before_epoch = SubtensorModule :: get_stake_for_hotkey_and_coldkey_on_subnet (
3225+ & miner_hotkey,
3226+ & miner_coldkey,
3227+ netuid,
3228+ ) ;
3229+
3230+ // step by one block
3231+ step_block ( 1 ) ;
3232+ // Verify that root alpha divs
3233+ let new_root_alpha_divs = PendingRootAlphaDivs :: < Test > :: get ( netuid) ;
3234+ // Check that we are NOT being subsidized, i.e. that root alpha divs are are changing
3235+ assert_ne ! (
3236+ new_root_alpha_divs, old_root_alpha_divs,
3237+ "Root alpha divs should be changing"
3238+ ) ;
3239+ assert ! (
3240+ new_root_alpha_divs > AlphaCurrency :: ZERO ,
3241+ "Root alpha divs should be greater than 0"
3242+ ) ;
3243+
3244+ // Run again but with some root stake
3245+ step_block ( subnet_tempo - 1 ) ;
3246+
3247+ let miner_uid = Uids :: < Test > :: get ( netuid, miner_hotkey) . unwrap_or ( 0 ) ;
3248+ let miner_incentive: AlphaCurrency =
3249+ ( * Incentive :: < Test > :: get ( NetUidStorageIndex :: from ( netuid) )
3250+ . get ( miner_uid as usize )
3251+ . expect ( "Miner uid should be present" ) as u64 )
3252+ . into ( ) ;
3253+ log:: info!( "Miner incentive: {miner_incentive:?}" ) ;
3254+
3255+ let per_block_emission = SubtensorModule :: get_block_emission_for_issuance (
3256+ SubtensorModule :: get_alpha_issuance ( netuid) . into ( ) ,
3257+ )
3258+ . unwrap_or ( 0 ) ;
3259+
3260+ // Miner emissions
3261+ let miner_emission_1: u64 = SubtensorModule :: get_stake_for_hotkey_and_coldkey_on_subnet (
3262+ & miner_hotkey,
3263+ & miner_coldkey,
3264+ netuid,
3265+ )
3266+ . to_u64 ( )
3267+ - miner_stake_before_epoch. to_u64 ( ) ;
3268+
3269+ assert_abs_diff_eq ! (
3270+ miner_emission_1,
3271+ U96F32 :: saturating_from_num( miner_incentive)
3272+ . saturating_div( u16 :: MAX . into( ) )
3273+ . saturating_mul( U96F32 :: saturating_from_num( per_block_emission) )
3274+ . saturating_mul( U96F32 :: saturating_from_num( subnet_tempo + 1 ) )
3275+ . saturating_mul( U96F32 :: saturating_from_num( 0.45 ) ) // miner cut
3276+ . saturating_to_num:: <u64 >( ) ,
3277+ epsilon = 1_000_000_u64
3278+ ) ;
3279+ } ) ;
3280+ }
0 commit comments