Skip to content

Fix: Era Info voting stake discrepancy when performing unstake/move operations#1476

Merged
ipapandinas merged 4 commits intomasterfrom
fix/dAppStaking-era-info
May 21, 2025
Merged

Fix: Era Info voting stake discrepancy when performing unstake/move operations#1476
ipapandinas merged 4 commits intomasterfrom
fix/dAppStaking-era-info

Conversation

@ipapandinas
Copy link
Contributor

@ipapandinas ipapandinas commented May 17, 2025

Pull Request Summary

This PR fixes a bug that caused discrepancies in the voting stake in EraInfo, particularly during unstake or move operations.

Context

Previously, the EraInfo::unstake_amount method incorrectly aggregated the unstaked voting and build_and_earn stakes using the total method, and subtracted the combined amount starting with build_and_earn. While this logic was acceptable for the current era (due to delayed staking eligibility after a move), it was incorrect for the next era leading to an inflated voting stake.

Fixes

  • Replaced the total-based subtraction in EraInfo::unstake_amount with a new subtract_stake method that subtracts voting and build_and_earn balances independently.
  • Applied the same fix to ContractStake to ensure consistency across smart contract staking records.
  • Moved the logic for converting voting stake into build_and_earn (when bonus is forfeited) into the SingularStakingInfo unstake flow. This is now performed explicitly during a move operation (before applying the inner_stake) and no longer handled during unstake operations.

The era_info_stakes_remain_synced test was implemented to reproduce the bug.

Check list

  • added or updated unit tests
  • add unit try-state tests
  • update Astar official documentation

@ipapandinas ipapandinas added dapps-staking Dapps Staking runtime This PR/Issue is related to the topic “runtime”. labels May 17, 2025
PierreOssun
PierreOssun previously approved these changes May 19, 2025
Copy link
Contributor

@PierreOssun PierreOssun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good !

Copy link
Contributor

@Dinonard Dinonard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also do the test with chopsticks.
You can replay the block on which the issue first appeared, but with the runtime that you build from your PR.

Comment on lines +721 to +725
// expected to be non-zero in case we're past the voting sub-period
if !post_era_info.total_staked_amount().is_zero() {
// not fully correct, but good enough for unstake tests
assert!(
post_era_info.current_stake_amount.voting >= post_era_info.next_stake_amount.voting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the 2nd comment assuming that for move operation it might be untrue. If it's not, the comment can be removed, or at least the wording can be changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small adjustment here, the voting stake must be strictly equal for current/next era for unstake operations.

assert_eq!(
post_era_info.total_staked_amount(),
pre_era_info.total_staked_amount() - amount,
pre_era_info.total_staked_amount().saturating_sub(amount),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to keep the old -, because if underflow happens, the test will crash.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, reverted

contract_stake.stake(stake_amount, era_1, period);
let total_stake_amount = stake_amount.total();

// 1st scenario - unstake some amount from Voting stake don't affect B&E stake
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you intend to add more scenarios here?
Asking just because of the comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small leftover. No additional scenarios are planned here. I have modified the comment.

@ipapandinas
Copy link
Contributor Author

@Dinonard - I've tested both unstake and move operations with Chopsticks, everything works as expected now

@github-actions
Copy link

Code Coverage

Package Line Rate Branch Rate Health
pallets/xc-asset-config/src 62% 0%
pallets/static-price-provider/src 91% 0%
precompiles/unified-accounts/src 100% 0%
precompiles/dapp-staking/src 89% 0%
pallets/vesting-mbm/src 87% 0%
chain-extensions/unified-accounts/src 0% 0%
pallets/collective-proxy/src 94% 0%
pallets/dapp-staking/src/test 0% 0%
pallets/ethereum-checked/src 76% 0%
pallets/astar-xcm-benchmarks/src 86% 0%
pallets/collator-selection/src 86% 0%
chain-extensions/types/assets/src 0% 0%
pallets/astar-xcm-benchmarks/src/fungible 100% 0%
chain-extensions/types/unified-accounts/src 0% 0%
pallets/unified-accounts/src 80% 0%
precompiles/assets-erc20/src 77% 0%
precompiles/dapp-staking/src/test 0% 0%
pallets/dapp-staking/src/benchmarking 95% 0%
pallets/dapp-staking/src 80% 0%
pallets/dapp-staking/rpc/runtime-api/src 0% 0%
pallets/dynamic-evm-base-fee/src 84% 0%
primitives/src 54% 0%
precompiles/sr25519/src 56% 0%
chain-extensions/pallet-assets/src 54% 0%
primitives/src/xcm 62% 0%
precompiles/xcm/src 69% 0%
pallets/inflation/src 83% 0%
precompiles/dispatch-lockdrop/src 83% 0%
pallets/price-aggregator/src 75% 0%
pallets/astar-xcm-benchmarks/src/generic 100% 0%
precompiles/substrate-ecdsa/src 67% 0%
Summary 77% (3644 / 4754) 0% (0 / 0)

Minimum allowed line rate is 50%

@Dinonard
Copy link
Contributor

@Dinonard - I've tested both unstake and move operations with Chopsticks, everything works as expected now

That's good!

Just to make sure we're on the same page, I meant to say to re-run the old blocks using the new runtime.
chopsticks run-block ...

@ipapandinas ipapandinas merged commit fc0c1aa into master May 21, 2025
8 checks passed
@ipapandinas ipapandinas deleted the fix/dAppStaking-era-info branch May 21, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dapps-staking Dapps Staking runtime This PR/Issue is related to the topic “runtime”.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants