The analysis of the security advisory and the associated patch commit e65c3a55a398a403103f1b089cf76f0d4befc7a0 points to a logic flaw in the x/costaking module of the Babylon chain. The root cause of the vulnerability is an incorrect state update when a BTC delegation is unbonded at the same time as its associated Finality Provider (FP) becomes inactive.
The vulnerable function is HookFinality.AfterBtcDelegationUnbonded located in x/costaking/keeper/hooks_finality.go. The original implementation contained a faulty condition (if !isFpActiveInPrevSet || !isFpActiveInCurrSet) that prevented the subtraction of staked satoshis (ActiveSatoshis) from a delegator's account if the FP was active in the previous block but inactive in the current block. This scenario allowed the delegator's account to maintain a non-zero ActiveSatoshis balance, or "phantom stake," even after their BTC was fully unbonded, leading to undue reward accrual.
The patch corrects this by changing the condition to if !isFpActiveInPrevSet. This ensures that as long as the FP was active in the block preceding the unbonding event, the delegator's ActiveSatoshis are correctly reduced, regardless of the FP's status in the current block. This prevents the creation of phantom stake. The patch also introduces an upgrade handler (ResetCoStakerRwdsTracker) to retroactively fix the state of any accounts that were affected by this bug.