Bitter Khaki Iguana
Medium
BeforeValidatorSlashed
calculates thisVotingPower
without applying fraction
.
A validator can be partially slashed (fraction
) depending on the infraction, as such the calculation of threshold
of slashed voting power would be incorrect.
// BeforeValidatorSlashed records the slash event
func (h Hooks) BeforeValidatorSlashed(ctx context.Context, valAddr sdk.ValAddress, fraction math.LegacyDec) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
thresholds := []float64{float64(1) / float64(3), float64(2) / float64(3)}
epochNumber := h.k.GetEpoch(ctx).EpochNumber
totalVotingPower := h.k.GetTotalVotingPower(ctx, epochNumber)
// calculate total slashed voting power
slashedVotingPower := h.k.GetSlashedVotingPower(ctx, epochNumber)
// voting power of this validator
@> thisVotingPower, err := h.k.GetValidatorVotingPower(ctx, epochNumber, valAddr)
thisVal := types.Validator{Addr: valAddr, Power: thisVotingPower}
if err != nil {
// It's possible that the most powerful validator outside the validator set enrols to the validator after this validator is slashed.
// Consequently, here we cannot find this validator in the validatorSet map.
// As we consider the validator set in the epoch beginning to be the validator set throughout this epoch, we consider this new validator in the edge to have no voting power and return directly here.
return err
}
for _, threshold := range thresholds {
// if a certain threshold voting power is slashed in a single epoch, emit event and trigger hook
@> if float64(slashedVotingPower) < float64(totalVotingPower)*threshold && float64(totalVotingPower)*threshold <= float64(slashedVotingPower+thisVotingPower) {
slashedVals := h.k.GetSlashedValidators(ctx, epochNumber)
slashedVals = append(slashedVals, thisVal)
event := types.NewEventSlashThreshold(slashedVotingPower, totalVotingPower, slashedVals)
if err := sdkCtx.EventManager().EmitTypedEvent(&event); err != nil {
panic(err)
}
h.k.BeforeSlashThreshold(ctx, slashedVals)
}
}
// add the validator address to the set
if err := h.k.AddSlashedValidator(ctx, valAddr); err != nil {
// same as above error case
return err
}
return nil
}
No response
No response
- Validator gets partially slashed by the staking module.
Wrong threshold calculations in order to trigger hook BeforeSlashThreshold
.
No response
No response