Skip to content

[BUG] Panic in SlashAndResetCounters can halt chain when validator not found #199

@Winnode

Description

@Winnode

[BUG] Panic in SlashAndResetCounters can halt chain when validator not found

Bug Description

Found panic() calls in the Oracle module's SlashAndResetCounters that shouldn't be there. Using panic in BeginBlocker is a really bad idea since it crashes all validators and stops the whole chain.

The problematic code is in x/oracle/keeper/slash.go:

Line 49:

validator, err := k.StakingKeeper.Validator(ctx, operator)
if err != nil {
    panic(err)
}

Line 54:

consAddr, err := validator.GetConsAddr()
if err != nil {
    panic(err)
}

This gets called from BeginBlocker:

x/oracle/abci.go BeginBlocker()
    → k.SlashAndResetCounters(ctx)
        → panic(err) if validator not found
  • What's broken? SlashAndResetCounters just panics on error instead of handling it properly
  • Which module? Oracle module (x/oracle/keeper/slash.go)
  • Why's this bad? Panic in BeginBlocker crashes every validator and kills the chain. Cosmos SDK docs are clear - don't use panic in ABCI methods.

Steps to Reproduce

  1. Got a validator with VotePenaltyCounter in oracle module
  2. Tombstone/remove that validator from staking (penalty counter stays tho)
  3. Wait for SlashWindow to finish
  4. BeginBlocker calls SlashAndResetCounters
  5. Code tries to get validator data → errors out → panics → chain dies

Quick verification:

grep -n 'panic' ~/kiichain/x/oracle/keeper/slash.go
# Output:
# 49:                             panic(err)
# 54:                                     panic(err)

PoC test shows:

cd ~/kiichain && go test -v -run TestPanicInSlashAndResetCounters ./x/oracle/keeper/

# Output:
# Panic value:    validator does not exist
# /root/kiichain/x/oracle/keeper/slash.go:49

Expected Behavior

Validators should just log errors and move on, not crash. According to Cosmos SDK docs, ABCI methods (BeginBlocker, EndBlocker) shouldn't panic under any circumstance.


Actual Behavior

When StakingKeeper.Validator() hits an error, everything goes south:

  • All validators run the same code at the same block
  • They all panic at once
  • Every validator crashes
  • Chain completely halts

Environment

  • Kiichain version / commit: v6.0.0 (commit 4d52338)
  • Network: testnet oro
  • File: x/oracle/keeper/slash.go lines 49, 54
  • Related: x/oracle/abci.go BeginBlocker

Impact Assessment

Severity: Critical

  • Consensus failure: Yeah - all validators crash at the same block
  • Fund loss: Not directly, but users can't access funds while chain's down
  • Security risk: Yep - someone could trigger this intentionally
  • Chain halt: Absolutely - needs coordinated manual restart

Similar bug was caught in Nibiru's audit:
https://reports.zellic.io/publications/nibiru/findings/high-xinflation-xoracle-panic-in-endblock-hooks-will-halt-the-chain


Suggested Fix

// Before (vulnerable)
validator, err := k.StakingKeeper.Validator(ctx, operator)
if err != nil {
    panic(err)
}

// After (safe)
validator, err := k.StakingKeeper.Validator(ctx, operator)
if err != nil {
    ctx.Logger().Error("failed to get validator", "operator", operator.String(), "error", err)
    return false, nil
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions