Incorrect behavior of BridgedInflationCurve #57
Labels
No Label
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: ghostchain/ghost-node#57
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Problem
During the recent redeployment of the
ghost-slow-clapfunctionality, we observed unusual behavior during the sixth era. The total accumulated commissions reached approximately1.3 CSPR,yet no distributions occurred at the end of the 6th era. Specifically, theera_payoutreturned(0, 0)and did not failed.A special thanks to the ghostie known as Sauron for bringing this to our attention.
Findings
The only way this issue could occur is due to an overflow or underflow in
checked_mulor checked_div, which caused a fallback to theNonebranch, resulting in the return of twoDefault::default()values, equating to 0 for the currenttype Balance = u128. You can check this by your hand here.After a thorough investigation, we identified two key issues:
BridgedImbalanceis not being nullified, whileAccumulatedCommissionis.payout.Nullification
The purpose of
BridgedImbalanceandAccumulatedCommissionis to track imbalances and commissions throughout the era, as we need to eliminate the impact of bridging on the current validators. This is crucial because validators are incentivized by the reward curve to achieve the so-called ideal ratio of staked coins. During the bridging process, after a successful applause, the number of coins should either be minted or burned, which directly affects thetotal_issuanceand consequently alters the current ratio of staked coins.To obtain the initial
total_issuancethat remains unaffected by bridging actions in each era, we need to recalculate it in the adjusted total issuance. At the end of the era finalization, it is essential to nullify not onlyAccumulatedCommissionsbutBridgedImbalancetoo in ordre to make sure the adjusted total issuance will not stuck.Overflow
Since staking relies on the
PiecewiseLineartrait, there is a function that defines:As you can see, we are calling it here. However, instead of multiplying the result by
dat the end, we need to multiply it byaccumulated_commission. Therefore, we should multiply byaccumulated_commissionand then divide byadjusted_total_issuance(actuallydfor the function above) to make sure that reward is dependant onaccumulated_commissionnot ontotal_issuance.As an example, what occured in 6th era:
This is clearly an overflow of
u128, whereu128::MAXis approximately3.4028237e+38. As a result, we received zero as the payout. This situation is absolutely unacceptable, especially since we can expect commissions to be significantly higher in the future.Fixes
BridgedImbalanceto its default value during the call tonullify_commissionat the end of the era finalization. You can find how it was fixed here.Bug Bounty
We are 99.999% confident in the current implementation of
MulDiv; however, if you discover any failing test cases or have suggestions for optimizing the implementation, please share your thoughts in the comments below or reach out through any of our community channels:Use the latest version from
pallet-networksbranch and code inpallets/networksfolder as a referrence.Rewards are TBD