Skip to content

Latest commit

 

History

History
53 lines (39 loc) · 2.25 KB

072.md

File metadata and controls

53 lines (39 loc) · 2.25 KB

Spare Navy Cod

High

slashedVotingPower can be inflated if validator is slashed multiple times in one epoch

Overview

The hook BeforeValidatorSlashed calls AddSlashedValidator in the epoching module. The problem is that none of these functions track whether the validator is already slashed or not. As a result second slash call store.Set(valAddr, power) overwrites the same key with the same power and (worse) inflate the total slashed power slashedVotingPower + power.

func (k Keeper) AddSlashedValidator(ctx context.Context, valAddr sdk.ValAddress) error {
	epochNumber := k.GetEpoch(ctx).EpochNumber
	store := k.slashedValSetStore(ctx, epochNumber)
	thisVotingPower, err := k.GetValidatorVotingPower(ctx, epochNumber, valAddr)
	if err != nil {
		panic(errorsmod.Wrap(types.ErrMarshal, err.Error()))
	}
	thisVotingPowerBytes, err := sdkmath.NewInt(thisVotingPower).Marshal()
	if err != nil {
		panic(errorsmod.Wrap(types.ErrMarshal, err.Error()))
	}

	// insert into "set of slashed addresses" as KV pair, where
	// - key: valAddr
	// - value: thisVotingPower
	store.Set(valAddr, thisVotingPowerBytes)

	// add voting power
	slashedVotingPower := k.GetSlashedVotingPower(ctx, epochNumber)
	if err != nil {
		// we don't panic here since it's possible that the most powerful validator outside the validator set enrols to the validator after this validator is slashed.
		return err
	}
	k.setSlashedVotingPower(ctx, epochNumber, slashedVotingPower+thisVotingPower)
	return nil
}

See the function : https://github.com/sherlock-audit/2024-12-babylon/blob/main/babylon/x/epoching/keeper/epoch_slashed_val_set.go#L56C1-L81C2

Impact

Inflated slashedVotingPower can trigger threshold events prematurely (e.g., crossing 1/3 or 2/3) preventing the system for achieving enough voting power.

Likelihood

As far as I understand, a cosmos validator can be slashed multiple times in one epoch (which extends over multiple blocks) if he performs more "slahable" events. If the slashing is partial (slashFactor) validators stake is partially slashed, however his voting power in epoching module is always used fully.

Mitigation

Check that valAddr is not already included in the storage to avoid two slashing updates. Or/and do not append new value to the total sum