Skip to content

fix(provider): move MsgChangeRewardDenoms validation to msg server handler#2627

Open
Aboudjem wants to merge 1 commit intocosmos:mainfrom
Aboudjem:fix/move-validate-basic-to-msg-server
Open

fix(provider): move MsgChangeRewardDenoms validation to msg server handler#2627
Aboudjem wants to merge 1 commit intocosmos:mainfrom
Aboudjem:fix/move-validate-basic-to-msg-server

Conversation

@Aboudjem
Copy link
Copy Markdown

@Aboudjem Aboudjem commented Apr 9, 2026

Closes #2149

Moves the denom validation logic from MsgChangeRewardDenoms.ValidateBasic() into the ChangeRewardDenoms msg server handler, following the cosmos-sdk v0.50 pattern where ValidateBasic is soft-deprecated.

The validation checks (empty denoms, invalid denom format, denom in both add and remove sets) are now performed in the handler. ValidateBasic stubs to nil. Also swapped sdk.NewCoin().IsValid() for sdk.ValidateDenom() to avoid a panic on malformed input.

Tests added to msg_server_test.go covering the moved validation paths.

@github-actions github-actions Bot added the C:x/provider Assigned automatically by the PR labeler label Apr 9, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 9, 2026

Greptile Summary

This PR moves the MsgChangeRewardDenoms validation logic (empty-set check, denom format validation, add/remove overlap check) from ValidateBasic() into the ChangeRewardDenoms msg server handler, following the cosmos-sdk v0.50 soft-deprecation of ValidateBasic. It also replaces the panic-prone sdk.NewCoin().IsValid() call with the safer sdk.ValidateDenom(). New unit tests cover the moved validation paths.

Confidence Score: 5/5

Safe to merge — the refactoring is correct, the panic fix is an improvement, and all remaining findings are non-blocking style/coverage suggestions.

All P0/P1 behaviour is preserved: authority check still runs first, all three validation rules are enforced in the handler, and sdk.ValidateDenom is a strict superset of the old IsValid() denom check. The two findings (missing t.Run and a missing DenomsToRemove test case) are P2 quality-of-life improvements that do not affect correctness.

msg_server_test.go — minor test-isolation and coverage gaps, no correctness impact.

Vulnerabilities

No security concerns identified. The authority check remains the first guard in the handler, and sdk.ValidateDenom safely returns an error rather than panicking on malformed input.

Important Files Changed

Filename Overview
x/ccv/provider/keeper/msg_server.go Validation logic (empty check, denom format via sdk.ValidateDenom, overlap check) correctly moved into handler before the keeper call; order with the authority check is preserved.
x/ccv/provider/types/msg.go ValidateBasic stubbed to nil per cosmos-sdk v0.50 pattern; sdk.HasValidateBasic interface assertion retained; no import issues.
x/ccv/provider/keeper/msg_server_test.go New TestChangeRewardDenomsValidation covers 4 paths but lacks t.Run isolation and a test for invalid denom in DenomsToRemove.
CHANGELOG.md Entry correctly added under Unreleased > IMPROVEMENTS with issue reference.

Sequence Diagram

sequenceDiagram
    participant Client
    participant MsgServer as ChangeRewardDenoms Handler
    participant Keeper

    Client->>MsgServer: MsgChangeRewardDenoms
    MsgServer->>MsgServer: Check authority
    alt authority mismatch
        MsgServer-->>Client: ErrUnauthorized
    end
    MsgServer->>MsgServer: Check DenomsToAdd and DenomsToRemove not both empty
    alt both empty
        MsgServer-->>Client: ErrInvalidMsgChangeRewardDenoms
    end
    MsgServer->>MsgServer: sdk.ValidateDenom each denom in DenomsToAdd
    alt invalid denom
        MsgServer-->>Client: ErrInvalidMsgChangeRewardDenoms
    end
    MsgServer->>MsgServer: sdk.ValidateDenom each denom in DenomsToRemove + overlap check
    alt invalid denom or overlap
        MsgServer-->>Client: ErrInvalidMsgChangeRewardDenoms
    end
    MsgServer->>Keeper: ChangeRewardDenoms(ctx, add, remove)
    Keeper-->>MsgServer: eventAttributes
    MsgServer-->>Client: MsgChangeRewardDenomsResponse
Loading

Reviews (1): Last reviewed commit: "fix(provider): move MsgChangeRewardDenom..." | Re-trigger Greptile

Comment on lines +430 to +437
for _, tc := range testCases {
_, err := msgServer.ChangeRewardDenoms(ctx, tc.msg)
if tc.expectError {
require.Error(t, err, tc.name)
} else {
require.NoError(t, err, tc.name)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Test cases lack subtest isolation

Without t.Run, a require failure in any earlier test case halts the entire function, meaning later cases (including the success path) are silently skipped. This also means the -run flag and test output can't identify individual cases. Consider wrapping each case:

Suggested change
for _, tc := range testCases {
_, err := msgServer.ChangeRewardDenoms(ctx, tc.msg)
if tc.expectError {
require.Error(t, err, tc.name)
} else {
require.NoError(t, err, tc.name)
}
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
_, err := msgServer.ChangeRewardDenoms(ctx, tc.msg)
if tc.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}

Comment on lines +393 to +428
testCases := []struct {
name string
msg *providertypes.MsgChangeRewardDenoms
expectError bool
}{
{
name: "both sets empty",
msg: &providertypes.MsgChangeRewardDenoms{Authority: authority},
expectError: true,
},
{
name: "invalid denom",
msg: &providertypes.MsgChangeRewardDenoms{
Authority: authority,
DenomsToAdd: []string{"!!!bad"},
},
expectError: true,
},
{
name: "denom in both add and remove",
msg: &providertypes.MsgChangeRewardDenoms{
Authority: authority,
DenomsToAdd: []string{"uatom"},
DenomsToRemove: []string{"uatom"},
},
expectError: true,
},
{
name: "valid",
msg: &providertypes.MsgChangeRewardDenoms{
Authority: authority,
DenomsToAdd: []string{"uatom"},
},
expectError: false,
},
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing test case for invalid denom in DenomsToRemove

The "invalid denom" case only exercises the DenomsToAdd path. The symmetric DenomsToRemove validation branch (lines 123–126 of msg_server.go) has no dedicated test, leaving a gap in coverage. Consider adding:

{
    name: "invalid denom in remove",
    msg: &providertypes.MsgChangeRewardDenoms{
        Authority:      authority,
        DenomsToRemove: []string{"!!!bad"},
    },
    expectError: true,
},

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C:x/provider Assigned automatically by the PR labeler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move message validation logic to msg_server.go

1 participant