From c2d2404980624a416a5db3924a26ebbfad3d64f4 Mon Sep 17 00:00:00 2001 From: Exca-DK Date: Sat, 1 Mar 2025 02:09:32 +0100 Subject: [PATCH] Save alloc --- accounts/abi/argument.go | 16 ++++++++++++--- accounts/abi/unpack_test.go | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index 227a088b7d..ebf1da4f91 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -182,10 +182,20 @@ func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface // without supplying a struct to unpack into. Instead, this method returns a list containing the // values. An atomic argument will be a list with one element. func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { - nonIndexedArgs := arguments.NonIndexed() - retval := make([]interface{}, 0, len(nonIndexedArgs)) + size := 0 + for _, arg := range arguments { + if arg.Indexed { + continue + } + size++ + } + + retval := make([]interface{}, 0, size) virtualArgs := 0 - for index, arg := range nonIndexedArgs { + for index, arg := range arguments { + if arg.Indexed { + continue + } marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) if err != nil { return nil, err diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index 7df7b9c403..74db298b3f 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -31,6 +31,46 @@ import ( "github.com/stretchr/testify/require" ) +func BenchmarkUnpack(b *testing.B) { + testCases := []struct { + def string + packed string + }{ + { + def: `[{"type": "uint32"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + }, + { + def: `[{"type": "uint32[]"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + } + for i, test := range testCases { + b.Run(strconv.Itoa(i), func(b *testing.B) { + def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) + abi, err := JSON(strings.NewReader(def)) + if err != nil { + b.Fatalf("invalid ABI definition %s: %v", def, err) + } + encb, err := hex.DecodeString(test.packed) + if err != nil { + b.Fatalf("invalid hex %s: %v", test.packed, err) + } + + b.ResetTimer() + + var result any + for range b.N { + result, _ = abi.Unpack("method", encb) + } + _ = result + }) + } +} + // TestUnpack tests the general pack/unpack tests in packing_test.go func TestUnpack(t *testing.T) { t.Parallel()