|
2 | 2 | use crate::mock::*;
|
3 | 3 | mod mock;
|
4 | 4 | use frame_support::assert_ok;
|
| 5 | +use pallet_subtensor::LastAddStakeIncrease; |
5 | 6 | use sp_core::U256;
|
6 | 7 | use substrate_fixed::types::I64F64;
|
7 | 8 |
|
@@ -309,3 +310,163 @@ fn test_coinbase_nominator_drainage_overflow() {
|
309 | 310 | log::debug!("Test completed");
|
310 | 311 | });
|
311 | 312 | }
|
| 313 | + |
| 314 | +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --test coinbase test_coinbase_nominator_drainage_no_affected_by_last_add_stake -- --nocapture |
| 315 | +#[test] |
| 316 | +fn test_coinbase_nominator_drainage_no_affected_by_last_add_stake() { |
| 317 | + new_test_ext(1).execute_with(|| { |
| 318 | + // 1. Set up the network and accounts |
| 319 | + let netuid: u16 = 1; |
| 320 | + let hotkey = U256::from(0); |
| 321 | + let coldkey = U256::from(3); |
| 322 | + let nominator1 = U256::from(1); |
| 323 | + let nominator2 = U256::from(2); |
| 324 | + |
| 325 | + log::debug!("Setting up network with netuid: {}", netuid); |
| 326 | + log::debug!("Hotkey: {:?}, Coldkey: {:?}", hotkey, coldkey); |
| 327 | + log::debug!("Nominators: {:?}, {:?}", nominator1, nominator2); |
| 328 | + |
| 329 | + // 2. Create network and register neuron |
| 330 | + add_network(netuid, 1, 0); |
| 331 | + register_ok_neuron(netuid, hotkey, coldkey, 100000); |
| 332 | + SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); |
| 333 | + |
| 334 | + log::debug!("Network created and neuron registered"); |
| 335 | + |
| 336 | + // 3. Set up balances and stakes |
| 337 | + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1000); |
| 338 | + SubtensorModule::add_balance_to_coldkey_account(&nominator1, 1500); |
| 339 | + SubtensorModule::add_balance_to_coldkey_account(&nominator2, 1500); |
| 340 | + |
| 341 | + log::debug!("Balances added to accounts"); |
| 342 | + |
| 343 | + // 4. Make the hotkey a delegate |
| 344 | + let vali_take = (u16::MAX as u64 / 10); |
| 345 | + assert_ok!(SubtensorModule::do_become_delegate( |
| 346 | + RuntimeOrigin::signed(coldkey), |
| 347 | + hotkey, |
| 348 | + vali_take as u16 |
| 349 | + )); |
| 350 | + |
| 351 | + log::debug!("Hotkey became a delegate with minimum take"); |
| 352 | + |
| 353 | + // Add stakes for nominators |
| 354 | + // Add the stake directly to their coldkey-hotkey account |
| 355 | + // This bypasses the accounting in stake delta |
| 356 | + SubtensorModule::increase_stake_on_coldkey_hotkey_account(&nominator1, &hotkey, 5e9 as u64); |
| 357 | + SubtensorModule::increase_stake_on_coldkey_hotkey_account(&nominator2, &hotkey, 5e9 as u64); |
| 358 | + let initial_stake = 5e9 as u64; |
| 359 | + |
| 360 | + // Make add_stake call for nominator1 |
| 361 | + // This should not affect the emission distribution |
| 362 | + |
| 363 | + // Will be greater than the bock emission |
| 364 | + LastAddStakeIncrease::<Test>::insert(hotkey, nominator1, 100); |
| 365 | + |
| 366 | + // Log the stakes for hotkey, nominator1, and nominator2 |
| 367 | + log::debug!( |
| 368 | + "Initial stakes - Hotkey: {}, Nominator1: {}, Nominator2: {}", |
| 369 | + SubtensorModule::get_stake_for_coldkey_and_hotkey(&coldkey, &hotkey), |
| 370 | + SubtensorModule::get_stake_for_coldkey_and_hotkey(&nominator1, &hotkey), |
| 371 | + SubtensorModule::get_stake_for_coldkey_and_hotkey(&nominator2, &hotkey) |
| 372 | + ); |
| 373 | + log::debug!("Stakes added for nominators"); |
| 374 | + |
| 375 | + // 5. Set emission and verify initial states |
| 376 | + let to_emit = 20_000e9 as u64; |
| 377 | + SubtensorModule::set_emission_values(&[netuid], vec![to_emit]).unwrap(); |
| 378 | + assert_eq!(SubtensorModule::get_subnet_emission_value(netuid), to_emit); |
| 379 | + assert_eq!(SubtensorModule::get_pending_hotkey_emission(&hotkey), 0); |
| 380 | + assert_eq!( |
| 381 | + SubtensorModule::get_total_stake_for_hotkey(&hotkey), |
| 382 | + initial_stake * 2 |
| 383 | + ); |
| 384 | + assert_eq!(SubtensorModule::get_pending_emission(netuid), 0); |
| 385 | + |
| 386 | + log::debug!("Emission set and initial states verified"); |
| 387 | + |
| 388 | + // 6. Set hotkey emission tempo |
| 389 | + SubtensorModule::set_hotkey_emission_tempo(1); |
| 390 | + log::debug!("Hotkey emission tempo set to 1"); |
| 391 | + |
| 392 | + // 7. Simulate blocks and check emissions |
| 393 | + next_block(); |
| 394 | + assert_eq!(SubtensorModule::get_pending_emission(netuid), to_emit); |
| 395 | + log::debug!( |
| 396 | + "After first block, pending emission: {}", |
| 397 | + SubtensorModule::get_pending_emission(netuid) |
| 398 | + ); |
| 399 | + |
| 400 | + next_block(); |
| 401 | + assert_eq!(SubtensorModule::get_pending_emission(netuid), 0); |
| 402 | + assert_eq!(SubtensorModule::get_pending_hotkey_emission(&hotkey), 0); |
| 403 | + log::debug!("After second block, pending emission drained"); |
| 404 | + |
| 405 | + // 8. Check final stakes |
| 406 | + let hotkey_stake = SubtensorModule::get_stake_for_coldkey_and_hotkey(&coldkey, &hotkey); |
| 407 | + let nominator1_stake = |
| 408 | + SubtensorModule::get_stake_for_coldkey_and_hotkey(&nominator1, &hotkey); |
| 409 | + let nominator2_stake = |
| 410 | + SubtensorModule::get_stake_for_coldkey_and_hotkey(&nominator2, &hotkey); |
| 411 | + |
| 412 | + log::debug!( |
| 413 | + "Final stakes - Hotkey: {}, Nominator1: {}, Nominator2: {}", |
| 414 | + hotkey_stake, |
| 415 | + nominator1_stake, |
| 416 | + nominator2_stake |
| 417 | + ); |
| 418 | + |
| 419 | + // 9. Verify distribution |
| 420 | + let total_emission = to_emit * 2; // to_emit per block for 2 blocks |
| 421 | + let hotkey_emission = (I64F64::from_num(total_emission) / I64F64::from_num(u16::MAX) |
| 422 | + * I64F64::from_num(vali_take)) |
| 423 | + .to_num::<u64>(); |
| 424 | + let remaining_emission = total_emission - hotkey_emission; |
| 425 | + let nominator_emission = remaining_emission / 2; |
| 426 | + |
| 427 | + log::debug!( |
| 428 | + "Calculated emissions - Hotkey: {}, Each Nominator: {}", |
| 429 | + hotkey_emission, |
| 430 | + nominator_emission |
| 431 | + ); |
| 432 | + |
| 433 | + // Debug: Print the actual stakes |
| 434 | + log::debug!("Actual hotkey stake: {}", hotkey_stake); |
| 435 | + log::debug!("Actual nominator1 stake: {}", nominator1_stake); |
| 436 | + log::debug!("Actual nominator2 stake: {}", nominator2_stake); |
| 437 | + |
| 438 | + // Debug: Check the total stake for the hotkey |
| 439 | + let total_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey); |
| 440 | + log::debug!("Total stake for hotkey: {}", total_stake); |
| 441 | + |
| 442 | + // Assertions |
| 443 | + let expected_hotkey_stake = 4_000e9 as u64; |
| 444 | + let eps = 0.5e9 as u64; |
| 445 | + assert!( |
| 446 | + hotkey_stake >= expected_hotkey_stake - eps |
| 447 | + && hotkey_stake <= expected_hotkey_stake + eps, |
| 448 | + "Hotkey stake mismatch - expected: {}, actual: {}", |
| 449 | + expected_hotkey_stake, |
| 450 | + hotkey_stake |
| 451 | + ); |
| 452 | + assert_eq!( |
| 453 | + nominator1_stake, |
| 454 | + initial_stake + nominator_emission, |
| 455 | + "Nominator1 stake mismatch" |
| 456 | + ); |
| 457 | + assert_eq!( |
| 458 | + nominator2_stake, |
| 459 | + initial_stake + nominator_emission, |
| 460 | + "Nominator2 stake mismatch" |
| 461 | + ); |
| 462 | + |
| 463 | + // 10. Check total stake |
| 464 | + assert_eq!( |
| 465 | + total_stake, |
| 466 | + initial_stake + initial_stake + total_emission, |
| 467 | + "Total stake mismatch" |
| 468 | + ); |
| 469 | + |
| 470 | + log::debug!("Test completed"); |
| 471 | + }); |
| 472 | +} |
0 commit comments