Skip to content

Commit bb4f50b

Browse files
test: add update_rewards toggle tokens flow test (#57)
<!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/starkware-libs/starknet-staking/57) <!-- Reviewable:end --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a comprehensive flow test that toggles enabled BTC tokens across attestation and consensus epochs and validates rewards behavior with update_rewards. > > - **Tests**: > - Add `update_rewards_token_enable_disable_flow_test` in `src/flow_test/test.cairo`: > - Adds two BTC tokens (8d/18d), toggles enable/disable across epochs, performs staking/delegation, attests, starts consensus, calls `update_rewards` (including twice in same epoch), and asserts staker/delegator rewards per token in attestation (v2) and consensus (v3) modes. > - Uses `NormalizedAmountTrait` and v2/v3 reward calculators for STRK/BTC. > - **Supporting changes**: > - Import updates: `NormalizedAmountTrait`; switch to/use `calculate_staker_btc_pool_rewards_v3`, `calculate_staker_strk_rewards_v2`, etc. > - Tidy `src/flow_test/flow_ideas.md` by simplifying the k=1 -> k=2 token item. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2dc8dac. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 6294afd commit bb4f50b

File tree

2 files changed

+181
-4
lines changed

2 files changed

+181
-4
lines changed

src/flow_test/flow_ideas.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,4 @@
2828
- Cover all ifs with migration from: V0, V1, V2.
2929

3030
## k=1 -> k=2 token
31-
- enable token, update rewards, advance epoch, update rewards, advance epoch, update rewards - token does not get rewards until after 2 epochs
32-
- same as above with disable (can be implemented together as one test)
3331
- enable token A and disable token B, next epoch upgrade, test views and rewards.

src/flow_test/test.cairo

Lines changed: 181 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ use staking::staking::interface::{
1616
IStakingConsensusDispatcherTrait, IStakingDispatcherTrait,
1717
IStakingRewardsManagerSafeDispatcherTrait,
1818
};
19+
use staking::staking::objects::NormalizedAmountTrait;
1920
use staking::staking::utils::{BTC_WEIGHT_FACTOR, STAKING_POWER_BASE_VALUE, STRK_WEIGHT_FACTOR};
2021
use 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
};
2425
use 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

Comments
 (0)