-
Notifications
You must be signed in to change notification settings - Fork 174
Description
ZetaChain Node - Bug Report
Repo: https://github.com/zeta-chain/node
Version: v37.0.0
Commit: 78e1a91
Date: 2026-01-11
Bug 1: VoteBlame crashes when VoteOnBallot fails
Severity: HIGH
File: x/observer/keeper/msg_server_vote_blame.go
Lines: 32-44
The Problem
Found a nil pointer bug in the blame voting handler. When VoteOnBallot returns an error, the code still tries to read ballot.BallotIdentifier for the error message. But ballot is nil at that point, so it panics.
Basically the error handling code itself causes a crash. Not great.
Why This Matters
- Node goes down if this gets triggered during blame voting
- Multiple validators hitting this = bad time for the network
- Any observer can trigger it by voting when conditions make
VoteOnBallotfail
The Code
// x/observer/keeper/msg_server_vote_blame.go:32-44
ballot, isFinalized, isNew, err := k.VoteOnBallot(
ctx,
observationChain,
msg.Digest(),
types.ObservationType_TSSKeySign,
msg.Creator,
types.VoteType_SuccessObservation,
)
if err != nil {
return nil, sdkerrors.Wrapf(
err,
"%s, BallotIdentifier %v", voteBlameID, ballot.BallotIdentifier) // boom - ballot is nil
}What Happens
panic: runtime error: invalid memory address or nil pointer dereference
Fix
Just check if ballot exists before using it:
if err != nil {
if ballot != nil {
return nil, sdkerrors.Wrapf(err, "%s, BallotIdentifier %v", voteBlameID, ballot.BallotIdentifier)
}
return nil, sdkerrors.Wrapf(err, "%s, failed to vote on ballot", voteBlameID)
}Link
https://github.com/zeta-chain/node/blob/78e1a91/x/observer/keeper/msg_server_vote_blame.go#L32-L44
Bug 2: Wrong order of nil check in ZRC20 functions
Severity: MEDIUM
File: x/fungible/keeper/zrc20_cosmos_coins_mapping.go
Lines: 96, 127
The Problem
Two functions check amount.Sign() before checking if amount is nil. Go evaluates left to right, so if you pass nil it crashes before the nil check even runs.
if amount.Sign() <= 0 || amount == nil { // wrong - crashes on nilShould be:
if amount == nil || amount.Sign() <= 0 { // right - nil check firstWhy This Matters
These are exported functions (CheckZRC20Allowance, CheckZRC20Balance). Right now nothing external calls them with nil, but if someone adds a precompile or new feature that does, the node crashes.
It's a bug waiting to happen.
The Code
// line 96
func (k Keeper) CheckZRC20Allowance(..., amount *big.Int) error {
if amount.Sign() <= 0 || amount == nil { // panic on nil
return fungibletypes.ErrInvalidAmount
}
}
// line 127
func (k Keeper) CheckZRC20Balance(..., amount *big.Int) error {
if amount.Sign() <= 0 || amount == nil { // same issue
return fungibletypes.ErrInvalidAmount
}
}Fix
Flip the order:
if amount == nil || amount.Sign() <= 0 {
return fungibletypes.ErrInvalidAmount
}Links
- https://github.com/zeta-chain/node/blob/78e1a91/x/fungible/keeper/zrc20_cosmos_coins_mapping.go#L96
- https://github.com/zeta-chain/node/blob/78e1a91/x/fungible/keeper/zrc20_cosmos_coins_mapping.go#L127
Bug 3: Feature flag function crashes on bad context
Severity: LOW
File: zetaclient/context/feature_flags.go
Lines: 10-14
The Problem
When FromContext fails, app is nil. But then the code tries to log with app.logger. Crash.
func EnableMultipleCallsFeatureFlag(ctx context.Context) bool {
app, err := FromContext(ctx)
if err != nil {
app.logger.Warn().Err(err)... // app is nil here
return false
}
}Why This Matters
Not consensus-critical since it's zetaclient code, but it can crash the client if context is messed up.
Fix
Don't try to use app when it's nil:
if err != nil {
return false // just return, can't log without app
}Link
https://github.com/zeta-chain/node/blob/78e1a91/zetaclient/context/feature_flags.go#L10-L14