Silent unpack failure lowers quorum
Description
In x/gov/keeper/proposal.go, each proposal message is unpacked with the following:
if err := k.cdc.UnpackAny(msg, &sdkMsg); err == nil {
// process message
}
If UnpackAny
returns an error, the code simply skips the message; no error is surfaced. When all messages in a proposal fail to unpack (e.g., due to corruption), ProposalKinds
stays empty (kinds == 0
).
Then, getQuorumAndThreshold()
evaluates
if kinds.HasKindConstitutionAmendment() || kinds.HasKindLaw() { /* higher quorum */ }
Both checks return false
, so the default (lowest-quorum) path executes. Thus, a corrupted constitution-amendment proposal would be evaluated with the minimal quorum.
Impact
The scenario is unlikely in normal operation because messages are validated during SubmitProposal
; however, if state corruption or future code changes allow a bad message through, the proposal would receive an unexpectedly low quorum requirement.
Recommendations
Guard against silent skips:
if err := k.cdc.UnpackAny(msg, &sdkMsg); err != nil {
return fmt.Errorf("failed to unpack proposal msg: %w", err)
}
Alternatively, track a flag indicating that at least one message unpacked successfully, and abort otherwise.
Remediation
This issue has been acknowledged by AtomOne, and a fix was implemented in PR #167↗.