-
Notifications
You must be signed in to change notification settings - Fork 1
Description
[BUG] Claim module uses time.Now() which breaks consensus
Summary
Found time.Now() in x/claim/types/params.go inside DefaultParams(). This gets called when genesis is created. Problem is each validator has different system clock, so they end up with different ClaimEndTime values. That means state mismatch = consensus failure.
Version
v1.9.0 (checked on Dec 2025)
Affected Networks
- Mainnet - yes, claim module is active (see lumera-networks/mainnet/genesis.json line 1265)
- Testnet - yes, claim module is active (see lumera-networks/testnet/genesis.json)
Where
x/claim/types/params.go line 18:
func DefaultParams() Params {
return NewParams(
true,
time.Now().Add(time.Hour*400).Unix(), // this is the issue
100,
)
}And it's used in x/claim/types/genesis.go:
func DefaultGenesis() *GenesisState {
return &GenesisState{
Params: DefaultParams(), // calls time.Now() here
ClaimRecords: []ClaimRecord{},
TotalClaimableAmount: DefaultClaimableAmountConst,
ClaimsDenom: DefaultClaimsDenom,
}
}Why it's bad
Say validator A boots up at 12:00:00 and validator B at 12:00:03. They'll compute different unix timestamps for ClaimEndTime. Doesn't matter if it's just 1 second off - different state hash = nodes disagree = chain halts.
This is a known no-no in cosmos dev. You're supposed to use ctx.BlockTime() for anything time-related in state machine code.
How to fix
Don't call time.Now() directly. Either:
- Set it to 0 in DefaultParams and let InitGenesis fill it using block time:
func DefaultParams() Params {
return NewParams(true, 0, 100)
}
// then in InitGenesis
if params.ClaimEndTime == 0 {
params.ClaimEndTime = ctx.BlockTime().Add(400 * time.Hour).Unix()
}- Or just use a hardcoded timestamp if you know when claiming should end
Severity
High/Critical - can cause chain halt during genesis or upgrade if validators init at different times
Tested on
- Repo: LumeraProtocol/lumera
- Tag: v1.9.0
- File still has the bug as of now