From 2db7369d6d80338acae434f8d45647272c6ba24c Mon Sep 17 00:00:00 2001 From: Ryan Tinianov Date: Wed, 12 Jun 2024 13:47:29 -0400 Subject: [PATCH] Fix decoding unnamed params, the return type was right, but names weren't populated for the arg itself. (#13512) --- core/services/relay/evm/codec_test.go | 27 +++++++++++++++++++ core/services/relay/evm/decoder.go | 8 +++++- core/services/relay/evm/types/codec_entry.go | 2 ++ .../relay/evm/types/codec_entry_test.go | 7 +++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/core/services/relay/evm/codec_test.go b/core/services/relay/evm/codec_test.go index c80002ebd70..638a9afd706 100644 --- a/core/services/relay/evm/codec_test.go +++ b/core/services/relay/evm/codec_test.go @@ -34,6 +34,33 @@ func TestCodec(t *testing.T) { anyN := 10 c := tester.GetCodec(t) + t.Run("Decode works with multiple unnamed return values", func(t *testing.T) { + encode := &struct { + F0 int32 + F1 int32 + }{F0: 1, F1: 2} + codecName := "my_codec" + evmEncoderConfig := `[{"Name":"","Type":"int32"},{"Name":"","Type":"int32"}]` + + codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ + codecName: {TypeABI: evmEncoderConfig}, + }} + c, err := evm.NewCodec(codecConfig) + require.NoError(t, err) + + result, err := c.Encode(testutils.Context(t), encode, codecName) + require.NoError(t, err) + + decode := &struct { + F0 int32 + F1 int32 + }{} + err = c.Decode(testutils.Context(t), result, decode, codecName) + require.NoError(t, err) + require.Equal(t, encode.F0, decode.F0) + require.Equal(t, encode.F1, decode.F1) + }) + t.Run("GetMaxEncodingSize delegates to GetMaxSize", func(t *testing.T) { actual, err := c.GetMaxEncodingSize(testutils.Context(t), anyN, sizeItemType) assert.NoError(t, err) diff --git a/core/services/relay/evm/decoder.go b/core/services/relay/evm/decoder.go index f16875d80f6..fdecf002020 100644 --- a/core/services/relay/evm/decoder.go +++ b/core/services/relay/evm/decoder.go @@ -18,7 +18,13 @@ type decoder struct { var _ commontypes.Decoder = &decoder{} -func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType string) error { +func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType string) (err error) { + defer func() { + // unexpected, but reflection can panic + if r := recover(); r != nil { + err = fmt.Errorf("%w: %v", commontypes.ErrInvalidType, r) + } + }() info, ok := m.Definitions[itemType] if !ok { return fmt.Errorf("%w: cannot find definition for %s", commontypes.ErrInvalidType, itemType) diff --git a/core/services/relay/evm/types/codec_entry.go b/core/services/relay/evm/types/codec_entry.go index b42bf9c0b08..38242c43a2d 100644 --- a/core/services/relay/evm/types/codec_entry.go +++ b/core/services/relay/evm/types/codec_entry.go @@ -146,11 +146,13 @@ func (entry *codecEntry) Init() (err error) { } for { name = name + "_X" + arg.Name = name if !seenNames[name] { break } } } + args[i] = arg seenNames[name] = true native[i] = reflect.StructField{Name: name, Type: nativeArg} checked[i] = reflect.StructField{Name: name, Type: checkedArg} diff --git a/core/services/relay/evm/types/codec_entry_test.go b/core/services/relay/evm/types/codec_entry_test.go index da1d4cc22a5..06b08fcecf2 100644 --- a/core/services/relay/evm/types/codec_entry_test.go +++ b/core/services/relay/evm/types/codec_entry_test.go @@ -219,11 +219,15 @@ func TestCodecEntry(t *testing.T) { assert.NoError(t, entry.Init()) ct := entry.CheckedType() require.Equal(t, 2, ct.NumField()) + args := entry.Args() + require.Equal(t, 2, len(args)) f0 := ct.Field(0) assert.Equal(t, "F0", f0.Name) + assert.Equal(t, "F0", args[0].Name) assert.Equal(t, reflect.TypeOf((*int64)(nil)), f0.Type) f1 := ct.Field(1) assert.Equal(t, "F1", f1.Name) + assert.Equal(t, "F1", args[1].Name) assert.Equal(t, reflect.TypeOf((*int32)(nil)), f1.Type) }) @@ -237,11 +241,14 @@ func TestCodecEntry(t *testing.T) { assert.NoError(t, entry.Init()) ct := entry.CheckedType() require.Equal(t, 2, ct.NumField()) + args := entry.Args() + require.Equal(t, 2, len(args)) f0 := ct.Field(0) assert.Equal(t, "F1", f0.Name) assert.Equal(t, reflect.TypeOf((*int64)(nil)), f0.Type) f1 := ct.Field(1) assert.Equal(t, "F1_X", f1.Name) + assert.Equal(t, "F1_X", args[1].Name) assert.Equal(t, reflect.TypeOf((*int32)(nil)), f1.Type) })