diff --git a/src/flow_test/flow_ideas.md b/src/flow_test/flow_ideas.md index ae9c05d9..f49ce581 100644 --- a/src/flow_test/flow_ideas.md +++ b/src/flow_test/flow_ideas.md @@ -40,12 +40,6 @@ - find sigma: Enter V0, change in V2, catch all ifs. - find sigma_edge_cases: catch the comments. - find sigma - cover all branches with member from V0, V1, V2(V2 DONE). -- member from V1(+V2), update balance at V3, pool gets rewards at V3, test rewards. (IDX=0) -- member from V1(+V2), update balance at V1, update balance at V3, test rewards. (IDX=1=LEN) -- member from V1(+V2), update balance at V1, pool gets rewards at V1, update balance at V3, test rewards. (IDX=1!=LEN) -- member from V1(+V2), pool gets rewards at V1, pool gets rewards at V1, update balance at V1, update balance at V3, test rewards (IDX=LEN) -- member from V1(+V2), pool gets_rewards at V1, pool gets rewards at V1, update balance at V1, pool gets rewards at V3, update balance at V3, test rewards. (REGULAR CASE) -- member from V1(+V2), pool gets_rewards at V1, pool gets rewards at V1, update balance at V1, pool gets rewards at V1 same epoch, pool gets rewards at V3, update balance at V3, test rewards. (REGULAR CASE) more ideas: - member from V1, pool gets rewards at V1, update balance at V1, update balance at V3, pool gets rewards at V3, test rewards. - member from V1, pool gets rewards at V1, pool gets rewards at V3, update balance at V3, test rewards. diff --git a/src/flow_test/flows.cairo b/src/flow_test/flows.cairo index 08a0fb8b..db35bdf8 100644 --- a/src/flow_test/flows.cairo +++ b/src/flow_test/flows.cairo @@ -7516,3 +7516,402 @@ pub(crate) impl DelegatorV0RewardsV1ChangeBalanceBeforeRewardsFlowImpl of FlowTr ); } } + +/// Flow: +/// Delegator enter in V1/V2. +/// Delegator change balance in V3. +/// Attest in V3 (pool gets rewards). +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationIdxIsZeroFlow { + pub(crate) staker: Option, + pub(crate) pool: Option, + pub(crate) delegator: Option, +} +pub(crate) impl DelegatorRewardsMigrationIdxIsZeroFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationIdxIsZeroFlow, +> { + fn versions(self: DelegatorRewardsMigrationIdxIsZeroFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationIdxIsZeroFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 2 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_epoch(); + self.staker = Option::Some(staker); + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationIdxIsZeroFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let staker = self.staker.unwrap(); + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount); + + // Pool gets rewards. + system.advance_k_epochs_and_attest(:staker); + let expected_rewards = calculate_strk_pool_rewards_v2( + staker_address: staker.staker.address, + staking_contract: system.staking.address, + minting_curve_contract: system.minting_curve.address, + ); + + // Test delegator rewards. + system.advance_epoch(); + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + let pool_balance = system.token.balance_of(account: pool); + assert!(pool_balance < 10); + assert_eq!(unclaimed_rewards, actual_rewards); + assert_eq!(actual_rewards, expected_rewards); + assert_eq!( + system.token.balance_of(account: delegator.reward.address), actual_rewards.into(), + ); + } +} + +/// Flow: +/// Delegator enter in V1/V2. +/// Delegator change balance in same version. +/// Delegator change balance in V3. +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationIdxLenIsOneFlow { + pub(crate) pool: Option, + pub(crate) delegator: Option, +} +pub(crate) impl DelegatorRewardsMigrationIdxLenIsOneFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationIdxLenIsOneFlow, +> { + fn versions(self: DelegatorRewardsMigrationIdxLenIsOneFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationIdxLenIsOneFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 3 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_epoch(); + system.increase_delegate(:delegator, :pool, amount: amount); + system.advance_epoch(); + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationIdxLenIsOneFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount / 2); + system.advance_epoch(); + + // Test delegator rewards. + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + assert!(unclaimed_rewards.is_zero()); + assert!(actual_rewards.is_zero()); + } +} + +/// Flow: +/// Delegator enter in V1/V2. +/// Delegator change balance in same version. +/// Attest in same version (pool gets rewards). +/// Delegator change balance in V3. +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationIdxIsOneFlow { + pub(crate) pool: Option, + pub(crate) delegator: Option, + pub(crate) expected_rewards: Option, +} +pub(crate) impl DelegatorRewardsMigrationIdxIsOneFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationIdxIsOneFlow, +> { + fn versions(self: DelegatorRewardsMigrationIdxIsOneFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationIdxIsOneFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 3 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_epoch(); + system.increase_delegate(:delegator, :pool, amount: amount); + system.advance_k_epochs_and_attest(:staker); + system.advance_epoch(); + + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + let expected_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + assert!(expected_rewards.is_non_zero()); + self.expected_rewards = Option::Some(expected_rewards); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationIdxIsOneFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount / 2); + system.advance_epoch(); + + // Test delegator rewards. + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + let expected_rewards = self.expected_rewards.unwrap(); + assert_eq!(unclaimed_rewards, expected_rewards); + assert_eq!(actual_rewards, expected_rewards); + } +} + + +/// Flow: +/// Delegator enter in V1/V2. +/// Attest in same version (pool gets rewards). +/// Attest in same version (pool gets rewards). +/// Delegator change balance in same version. +/// Delegator change balance in V3. +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationIdxIsLenFlow { + pub(crate) pool: Option, + pub(crate) delegator: Option, + pub(crate) expected_rewards: Option, +} +pub(crate) impl DelegatorRewardsMigrationIdxIsLenFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationIdxIsLenFlow, +> { + fn versions(self: DelegatorRewardsMigrationIdxIsLenFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationIdxIsLenFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 3 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_k_epochs_and_attest(:staker); + system.advance_k_epochs_and_attest(:staker); + system.add_to_delegation_pool(:delegator, :pool, amount: amount); + system.advance_epoch(); + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + let expected_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + assert!(expected_rewards.is_non_zero()); + self.expected_rewards = Option::Some(expected_rewards); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationIdxIsLenFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount / 2); + system.advance_epoch(); + + // Test delegator rewards. + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + let expected_rewards = self.expected_rewards.unwrap(); + assert_eq!(unclaimed_rewards, expected_rewards); + assert_eq!(actual_rewards, expected_rewards); + } +} + +/// Flow: +/// Delegator enter in V1/V2. +/// Attest in same version (pool gets rewards). +/// Attest in same version (pool gets rewards). +/// Delegator change balance in same version. +/// Attest in V3 (pool gets rewards). +/// Delegator change balance in V3. +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationFirstRegularCaseFlow { + pub(crate) staker: Option, + pub(crate) pool: Option, + pub(crate) delegator: Option, + pub(crate) expected_rewards: Option, +} +pub(crate) impl DelegatorRewardsMigrationFirstRegularCaseFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationFirstRegularCaseFlow, +> { + fn versions(self: DelegatorRewardsMigrationFirstRegularCaseFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationFirstRegularCaseFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 3 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_k_epochs_and_attest(:staker); + system.advance_k_epochs_and_attest(:staker); + system.add_to_delegation_pool(:delegator, :pool, amount: amount); + system.advance_epoch(); + self.staker = Option::Some(staker); + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + let expected_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + assert!(expected_rewards.is_non_zero()); + self.expected_rewards = Option::Some(expected_rewards); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationFirstRegularCaseFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let staker = self.staker.unwrap(); + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + let mut expected_rewards = self.expected_rewards.unwrap(); + + system.advance_k_epochs_and_attest(:staker); + expected_rewards += + calculate_strk_pool_rewards_v2( + staker_address: staker.staker.address, + staking_contract: system.staking.address, + minting_curve_contract: system.minting_curve.address, + ); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount / 2); + system.advance_epoch(); + + // Test delegator rewards. + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + assert_eq!(unclaimed_rewards, expected_rewards); + assert_eq!(actual_rewards, expected_rewards); + } +} + + +/// Flow: +/// Delegator enter in V1/V2. +/// Attest in same version (pool gets rewards). +/// Attest in same version (pool gets rewards). +/// Delegator change balance in same version. +/// Attest in same epoch same version (pool gets rewards). +/// Attest in V3 (pool gets rewards). +/// Delegator change balance in V3. +/// Test delegator rewards. +#[derive(Drop, Copy)] +pub(crate) struct DelegatorRewardsMigrationSecondRegularCaseFlow { + pub(crate) staker: Option, + pub(crate) pool: Option, + pub(crate) delegator: Option, + pub(crate) expected_rewards: Option, +} +pub(crate) impl DelegatorRewardsMigrationSecondRegularCaseFlowImpl of MultiVersionFlowTrait< + DelegatorRewardsMigrationSecondRegularCaseFlow, +> { + fn versions(self: DelegatorRewardsMigrationSecondRegularCaseFlow) -> Span { + [V1, V2].span() + } + + fn setup(ref self: DelegatorRewardsMigrationSecondRegularCaseFlow, ref system: SystemState) { + let amount = system.staking.get_min_stake(); + let staker = system.new_staker(:amount); + let commission = 200; + system.stake(:staker, :amount, pool_enabled: true, :commission); + let pool = system.staking.get_pool(:staker); + let delegator = system.new_delegator(amount: 3 * amount); + system.delegate(:delegator, :pool, :amount); + system.advance_k_epochs_and_attest(:staker); + system.advance_k_epochs_and_attest(:staker); + system.advance_epoch(); + system.add_to_delegation_pool(:delegator, :pool, :amount); + system.advance_block_custom_and_attest(:staker, stake: amount * 2); + system.advance_epoch(); + self.staker = Option::Some(staker); + self.pool = Option::Some(pool); + self.delegator = Option::Some(delegator); + let expected_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + assert!(expected_rewards.is_non_zero()); + self.expected_rewards = Option::Some(expected_rewards); + system.set_staker_for_migration(staker_address: staker.staker.address); + } + + fn test( + self: DelegatorRewardsMigrationSecondRegularCaseFlow, + ref system: SystemState, + version: ReleaseVersion, + ) { + let staker = self.staker.unwrap(); + let delegator = self.delegator.unwrap(); + let pool = self.pool.unwrap(); + let mut expected_rewards = self.expected_rewards.unwrap(); + + system.advance_k_epochs_and_attest(:staker); + expected_rewards += + calculate_strk_pool_rewards_v2( + staker_address: staker.staker.address, + staking_contract: system.staking.address, + minting_curve_contract: system.minting_curve.address, + ); + + // Delegator change balance. + let delegator_amount = system.pool_member_info_v1(:delegator, :pool).amount; + system.add_to_delegation_pool(:delegator, :pool, amount: delegator_amount / 2); + system.advance_epoch(); + + // Test delegator rewards. + let unclaimed_rewards = system.delegator_unclaimed_rewards(:delegator, :pool); + let actual_rewards = system.delegator_claim_rewards(:delegator, :pool); + assert_eq!(unclaimed_rewards, expected_rewards); + assert_eq!(actual_rewards, expected_rewards); + } +} diff --git a/src/flow_test/multi_version_tests.cairo b/src/flow_test/multi_version_tests.cairo index f54c57db..5cd777ea 100644 --- a/src/flow_test/multi_version_tests.cairo +++ b/src/flow_test/multi_version_tests.cairo @@ -168,3 +168,63 @@ fn find_sigma_migration_idx_is_one_flow_test() { }; test_multi_version_flow_mainnet(ref :flow); } + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_idx_is_zero_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationIdxIsZeroFlow { + staker: Option::None, pool: Option::None, delegator: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +} + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_idx_is_one_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationIdxIsOneFlow { + pool: Option::None, delegator: Option::None, expected_rewards: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +} + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_idx_len_is_one_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationIdxLenIsOneFlow { + pool: Option::None, delegator: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +} + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_idx_is_len_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationIdxIsLenFlow { + pool: Option::None, delegator: Option::None, expected_rewards: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +} + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_first_regular_case_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationFirstRegularCaseFlow { + staker: Option::None, + pool: Option::None, + delegator: Option::None, + expected_rewards: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +} + +#[test] +#[fork("MAINNET_LATEST")] +fn delegator_rewards_migration_second_regular_case_flow_test() { + let mut flow = flows::DelegatorRewardsMigrationSecondRegularCaseFlow { + staker: Option::None, + pool: Option::None, + delegator: Option::None, + expected_rewards: Option::None, + }; + test_multi_version_flow_mainnet(ref :flow); +}