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-clap
functionality, 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_payout
returned(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_mul
or checked_div
, which caused a fallback to theNone
branch, 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:
BridgedImbalance
is not being nullified, whileAccumulatedCommission
is.payout
.Nullification
The purpose of
BridgedImbalance
andAccumulatedCommission
is 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_issuance
and consequently alters the current ratio of staked coins.To obtain the initial
total_issuance
that 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 onlyAccumulatedCommissions
butBridgedImbalance
too in ordre to make sure the adjusted total issuance will not stuck.Overflow
Since staking relies on the
PiecewiseLinear
trait, there is a function that defines:As you can see, we are calling it here. However, instead of multiplying the result by
d
at the end, we need to multiply it byaccumulated_commission
. Therefore, we should multiply byaccumulated_commission
and then divide byadjusted_total_issuance
(actuallyd
for the function above) to make sure that reward is dependant onaccumulated_commission
not ontotal_issuance
.As an example, what occured in 6th era:
This is clearly an overflow of
u128
, whereu128::MAX
is 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
BridgedImbalance
to its default value during the call tonullify_commission
at 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-networks
branch and code inpallets/networks
folder as a referrence.Rewards are TBD