diff --git a/CHANGELOG.md b/CHANGELOG.md index 093e195728..05a7a8d185 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Bump Cosmos SDK dependencies to v0.53. ([\#2594](https://github.com/cosmos/interchain-security/pull/2594)) +### BUG FIXES + +- `[x/ccv]` Return an error when the transfer memo is missing the provider reward memo. ([\#2626](https://github.com/cosmos/interchain-security/pull/2626)) + ## v6.4.1 *February 25, 2025* diff --git a/x/ccv/types/wire.go b/x/ccv/types/wire.go index 9e49d546da..035f9624c5 100644 --- a/x/ccv/types/wire.go +++ b/x/ccv/types/wire.go @@ -236,7 +236,7 @@ func GetRewardMemoFromTransferMemo(memo string) (RewardMemo, error) { providerMemo, ok := memoData["provider"] if !ok { - return RewardMemo{}, err + return RewardMemo{}, errors.New("missing provider reward memo") } rewardMemo := RewardMemo{} diff --git a/x/ccv/types/wire_test.go b/x/ccv/types/wire_test.go index 2c0bc50fc9..599c63fe5b 100644 --- a/x/ccv/types/wire_test.go +++ b/x/ccv/types/wire_test.go @@ -237,3 +237,58 @@ func TestCreateTransferMemo(t *testing.T) { require.Equal(t, chainId, rewardMemo.ChainId) require.Equal(t, "ICS rewards", rewardMemo.Memo) } + +func TestGetRewardMemoFromTransferMemo(t *testing.T) { + testCases := []struct { + name string + memo string + expectErr bool + want types.RewardMemo + }{ + { + name: "missing provider key", + memo: `{"foo":"bar"}`, + expectErr: true, + }, + { + name: "invalid JSON", + memo: `{not-json}`, + expectErr: true, + }, + { + name: "provider present but wrong type", + memo: `{"provider":"not-an-object"}`, + expectErr: true, + }, + { + name: "provider present but missing fields", + memo: `{"provider":{"memo":"ICS rewards"}}`, + expectErr: false, + want: types.RewardMemo{Memo: "ICS rewards"}, + }, + { + name: "provider present and decodes", + memo: `{"provider":{"consumerId":"13","chainId":"chain-13","memo":"memo"}}`, + expectErr: false, + want: types.RewardMemo{ConsumerId: "13", ChainId: "chain-13", Memo: "memo"}, + }, + { + name: "valid ICS rewards memo", + memo: `{"provider":{"consumerId":"13","chainId":"chain-13","memo":"ICS rewards"}}`, + expectErr: false, + want: types.RewardMemo{ConsumerId: "13", ChainId: "chain-13", Memo: "ICS rewards"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rewardMemo, err := types.GetRewardMemoFromTransferMemo(tc.memo) + if tc.expectErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tc.want, rewardMemo) + }) + } +}