@@ -16,14 +16,16 @@ use staking::staking::interface::{
1616 IStakingConsensusDispatcherTrait , IStakingDispatcherTrait ,
1717 IStakingRewardsManagerSafeDispatcherTrait ,
1818};
19+ use staking :: staking :: objects :: NormalizedAmountTrait ;
1920use staking :: staking :: utils :: {BTC_WEIGHT_FACTOR , STAKING_POWER_BASE_VALUE , STRK_WEIGHT_FACTOR };
2021use staking :: test_utils :: constants :: {
2122 BTC_18D_CONFIG , BTC_5D_CONFIG , BTC_8D_CONFIG , PUBLIC_KEY , STRK_BASE_VALUE ,
2223 TEST_MIN_BTC_FOR_REWARDS ,
2324};
2425use staking :: test_utils :: {
25- StakingInitConfig , calculate_staker_btc_pool_rewards_v2,
26- calculate_staker_strk_rewards_with_balances_v2, calculate_staker_strk_rewards_with_balances_v3,
26+ StakingInitConfig , calculate_staker_btc_pool_rewards_v2, calculate_staker_btc_pool_rewards_v3,
27+ calculate_staker_strk_rewards_v2, calculate_staker_strk_rewards_with_balances_v2,
28+ calculate_staker_strk_rewards_with_balances_v3,
2729 calculate_strk_pool_rewards_with_pool_balance_v2,
2830 calculate_strk_pool_rewards_with_pool_balance_v3, compute_rewards_per_unit,
2931 custom_decimals_token, deploy_mock_erc20_decimals_contract,
@@ -3688,3 +3690,180 @@ fn delegator_claim_rewards_after_change_balance_flow_test() {
36883690 // Allow small rounding errors.
36893691 assert! (wide_abs_diff (rewards , expected_rewards_v3 * 2 ) <= 1 );
36903692}
3693+
3694+ /// Flow:
3695+ /// Add tokens A and B
3696+ /// Enable token B
3697+ /// Advance K epochs
3698+ /// Enable token A, disable token B
3699+ /// Attest
3700+ /// Advance epoch - test rewards only for token B
3701+ /// Attest
3702+ /// Advance epoch - test rewards only for token B
3703+ /// Attest
3704+ /// Advance epoch - test rewards only for token A
3705+ /// Start consensus rewards
3706+ /// Enable token B, disable token A
3707+ /// update_rewards twice in the same epoch
3708+ /// Advance epoch - test rewards only for token A
3709+ /// update_rewards
3710+ /// Advance epoch - test rewards only for token A
3711+ /// update_rewards
3712+ /// Advance epoch - test rewards only for token B
3713+ #[test]
3714+ fn update_rewards_token_enable_disable_flow_test () {
3715+ let cfg : StakingInitConfig = Default :: default ();
3716+ let mut system = SystemConfigTrait :: basic_stake_flow_cfg (: cfg ). deploy ();
3717+ let token_a_decimals = 8 ;
3718+ let token_b_decimals = 18 ;
3719+ let token_a = system . deploy_new_btc_token (name : " Token A" , decimals : token_a_decimals );
3720+ let token_b = system . deploy_new_btc_token (name : " Token B" , decimals : token_b_decimals );
3721+ let staking_contract = system . staking. address;
3722+ let minting_curve_contract = system . minting_curve. address;
3723+
3724+ // Setup tokens
3725+ system . staking. add_token (token_address : token_a . contract_address ());
3726+ system . staking. add_token (token_address : token_b . contract_address ());
3727+ system . staking. enable_token (token_address : token_b . contract_address ());
3728+
3729+ // Stake and delegate
3730+ let stake_amount = system . staking. get_min_stake ();
3731+ let delegation_amount_a = BTC_8D_CONFIG . min_for_rewards;
3732+ let delegation_amount_b = BTC_18D_CONFIG . min_for_rewards;
3733+ let staker = system . new_staker (amount : stake_amount );
3734+ let commission = 200 ;
3735+ system . stake (: staker , amount : stake_amount , pool_enabled : true , : commission );
3736+ let pool_a = system . set_open_for_delegation (: staker , token_address : token_a . contract_address ());
3737+ let pool_b = system . set_open_for_delegation (: staker , token_address : token_b . contract_address ());
3738+ let delegator_a = system . new_btc_delegator (amount : delegation_amount_a , token : token_a );
3739+ let delegator_b = system . new_btc_delegator (amount : delegation_amount_b , token : token_b );
3740+ system
3741+ . delegate_btc (
3742+ delegator : delegator_a , pool : pool_a , amount : delegation_amount_a , token : token_a ,
3743+ );
3744+ system
3745+ . delegate_btc (
3746+ delegator : delegator_b , pool : pool_b , amount : delegation_amount_b , token : token_b ,
3747+ );
3748+ system . advance_k_epochs ();
3749+
3750+ // Enable token A, disable token B
3751+ system . staking. enable_token (token_address : token_a . contract_address ());
3752+ system . staking. disable_token (token_address : token_b . contract_address ());
3753+
3754+ // Attest
3755+ system . advance_block_into_attestation_window (: staker );
3756+ system . attest (: staker );
3757+ system . advance_epoch ();
3758+
3759+ // Calculate rewards
3760+ let staker_info = system . staker_info_v1 (: staker );
3761+ let staker_rewards = system . staker_claim_rewards (: staker );
3762+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3763+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3764+ let (expected_staker_rewards , _ ) = calculate_staker_strk_rewards_v2 (
3765+ : staker_info , : staking_contract , : minting_curve_contract ,
3766+ );
3767+ assert! (expected_staker_rewards . is_non_zero ());
3768+ let (commission_rewards , expected_delegator_rewards ) = calculate_staker_btc_pool_rewards_v2 (
3769+ pool_balance : delegation_amount_b ,
3770+ : commission ,
3771+ : staking_contract ,
3772+ : minting_curve_contract ,
3773+ token_address : token_b . contract_address (),
3774+ );
3775+ assert! (commission_rewards . is_non_zero ());
3776+ assert! (expected_delegator_rewards . is_non_zero ());
3777+
3778+ // Test rewards
3779+ assert! (staker_rewards == expected_staker_rewards + commission_rewards );
3780+ assert! (delegator_a_rewards . is_zero ());
3781+ assert! (delegator_b_rewards == expected_delegator_rewards );
3782+
3783+ // Attest - test rewards only for token B
3784+ system . advance_block_into_attestation_window (: staker );
3785+ system . attest (: staker );
3786+ system . advance_epoch ();
3787+ let staker_rewards = system . staker_claim_rewards (: staker );
3788+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3789+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3790+ assert! (staker_rewards == expected_staker_rewards + commission_rewards );
3791+ assert! (delegator_a_rewards . is_zero ());
3792+ // Same rewards because the delegation amount is the same (with different decimals).
3793+ assert! (delegator_b_rewards == expected_delegator_rewards );
3794+
3795+ // Attest - test rewards only for token A
3796+ system . advance_block_into_attestation_window (: staker );
3797+ system . attest (: staker );
3798+ system . advance_epoch ();
3799+ let staker_rewards = system . staker_claim_rewards (: staker );
3800+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3801+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3802+ assert! (staker_rewards == expected_staker_rewards + commission_rewards );
3803+ assert! (delegator_a_rewards == expected_delegator_rewards );
3804+ assert! (delegator_b_rewards . is_zero ());
3805+
3806+ // Start consensus rewards
3807+ system . start_consensus_rewards ();
3808+
3809+ // Enable token B, disable token A
3810+ system . staking. enable_token (token_address : token_b . contract_address ());
3811+ system . staking. disable_token (token_address : token_a . contract_address ());
3812+
3813+ // Calculate rewards for consensus rewards - for single enabled token.
3814+ let (expected_staker_rewards , _ ) = calculate_staker_strk_rewards_with_balances_v3 (
3815+ amount_own : stake_amount ,
3816+ pool_amount : Zero :: zero (),
3817+ : commission ,
3818+ : staking_contract ,
3819+ : minting_curve_contract ,
3820+ );
3821+ assert! (expected_staker_rewards . is_non_zero ());
3822+ let (commission_rewards , expected_delegator_rewards ) = calculate_staker_btc_pool_rewards_v3 (
3823+ normalized_pool_balance : NormalizedAmountTrait :: from_native_amount (
3824+ amount : delegation_amount_a , decimals : token_a_decimals ,
3825+ ),
3826+ normalized_staker_total_btc_balance : NormalizedAmountTrait :: from_native_amount (
3827+ amount : delegation_amount_a , decimals : token_a_decimals ,
3828+ ),
3829+ : commission ,
3830+ : staking_contract ,
3831+ : minting_curve_contract ,
3832+ token_address : token_a . contract_address (),
3833+ );
3834+ assert! (commission_rewards . is_non_zero ());
3835+ assert! (expected_delegator_rewards . is_non_zero ());
3836+
3837+ // update_rewards - test rewards only for token A
3838+ system . update_rewards (: staker , disable_rewards : false );
3839+ advance_block_number_global (blocks : 1 );
3840+ system . update_rewards (: staker , disable_rewards : false );
3841+ system . advance_epoch ();
3842+ let staker_rewards = system . staker_claim_rewards (: staker );
3843+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3844+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3845+ assert! (staker_rewards == expected_staker_rewards * 2 + commission_rewards * 2 );
3846+ assert! (delegator_a_rewards == expected_delegator_rewards * 2 );
3847+ assert! (delegator_b_rewards . is_zero ());
3848+
3849+ // update_rewards - test rewards only for token A
3850+ system . update_rewards (: staker , disable_rewards : false );
3851+ system . advance_epoch ();
3852+ let staker_rewards = system . staker_claim_rewards (: staker );
3853+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3854+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3855+ assert! (staker_rewards == expected_staker_rewards + commission_rewards );
3856+ assert! (delegator_a_rewards == expected_delegator_rewards );
3857+ assert! (delegator_b_rewards . is_zero ());
3858+
3859+ // update_rewards - test rewards only for token B
3860+ system . update_rewards (: staker , disable_rewards : false );
3861+ system . advance_epoch ();
3862+ let staker_rewards = system . staker_claim_rewards (: staker );
3863+ let delegator_a_rewards = system . delegator_claim_rewards (delegator : delegator_a , pool : pool_a );
3864+ let delegator_b_rewards = system . delegator_claim_rewards (delegator : delegator_b , pool : pool_b );
3865+ assert! (staker_rewards == expected_staker_rewards + commission_rewards );
3866+ assert! (delegator_a_rewards . is_zero ());
3867+ // Same rewards because the delegation amount is the same (with different decimals).
3868+ assert! (delegator_b_rewards == expected_delegator_rewards );
3869+ }
0 commit comments