Skip to content

Commit 0ed8b83

Browse files
robert-zarembaholiman
authored andcommitted
accounts/abi: fix event unpack into slice
+ The event slice unpacker doesn't correctly extract element from the slice. The indexed arguments are not ignored as they should be (the data offset should not include the indexed arguments). + The `Elem()` call in the slice unpack doesn't work. The Slice related tests fails because of that. + the check in the loop are suboptimal and have been extracted out of the loop. + extracted common code from event and method tupleUnpack
1 parent 9becba5 commit 0ed8b83

File tree

5 files changed

+36
-23
lines changed

5 files changed

+36
-23
lines changed

accounts/abi/argument.go

+10
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,13 @@ func (a *Argument) UnmarshalJSON(data []byte) error {
4949

5050
return nil
5151
}
52+
53+
func countNonIndexedArguments(args []Argument) int {
54+
out := 0
55+
for i := range args {
56+
if !args[i].Indexed {
57+
out++
58+
}
59+
}
60+
return out
61+
}

accounts/abi/event.go

+10-13
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,19 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error {
5959
var (
6060
value = valueOf.Elem()
6161
typ = value.Type()
62+
kind = value.Kind()
6263
)
63-
64-
if value.Kind() != reflect.Struct {
65-
return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
64+
if err := requireUnpackKind(value, typ, kind, e.Inputs, true); err != nil {
65+
return err
6666
}
6767

68+
// `i` counts the nonindexed arguments.
69+
// `j` counts the number of complex types.
70+
// both `i` and `j` are used to to correctly compute `data` offset.
6871
i, j := -1, 0
6972
for _, input := range e.Inputs {
7073
if input.Indexed {
71-
// can't read, continue
74+
// Indexed arguments are not packed into data
7275
continue
7376
}
7477
i++
@@ -83,7 +86,7 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error {
8386
}
8487
reflectValue := reflect.ValueOf(marshalledValue)
8588

86-
switch value.Kind() {
89+
switch kind {
8790
case reflect.Struct:
8891
for j := 0; j < typ.NumField(); j++ {
8992
field := typ.Field(j)
@@ -95,19 +98,13 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error {
9598
}
9699
}
97100
case reflect.Slice, reflect.Array:
98-
if value.Len() < i {
99-
return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", i, value.Len())
100-
}
101101
v := value.Index(i)
102-
if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
103-
return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type())
102+
if err := requireAssignable(v, reflectValue); err != nil {
103+
return err
104104
}
105-
reflectValue := reflect.ValueOf(marshalledValue)
106105
if err := set(v.Elem(), reflectValue, input); err != nil {
107106
return err
108107
}
109-
default:
110-
return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
111108
}
112109
}
113110
return nil

accounts/abi/method.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error {
101101
var (
102102
value = valueOf.Elem()
103103
typ = value.Type()
104+
kind = value.Kind()
104105
)
106+
if err := requireUnpackKind(value, typ, kind, method.Outputs, false); err != nil {
107+
return err
108+
}
105109

106110
j := 0
107111
for i := 0; i < len(method.Outputs); i++ {
@@ -117,7 +121,7 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error {
117121
}
118122
reflectValue := reflect.ValueOf(marshalledValue)
119123

120-
switch value.Kind() {
124+
switch kind {
121125
case reflect.Struct:
122126
for j := 0; j < typ.NumField(); j++ {
123127
field := typ.Field(j)
@@ -129,19 +133,13 @@ func (method Method) tupleUnpack(v interface{}, output []byte) error {
129133
}
130134
}
131135
case reflect.Slice, reflect.Array:
132-
if value.Len() < i {
133-
return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(method.Outputs), value.Len())
134-
}
135136
v := value.Index(i)
136-
if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
137-
return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type())
137+
if err := requireAssignable(v, reflectValue); err != nil {
138+
return err
138139
}
139-
reflectValue := reflect.ValueOf(marshalledValue)
140140
if err := set(v.Elem(), reflectValue, method.Outputs[i]); err != nil {
141141
return err
142142
}
143-
default:
144-
return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
145143
}
146144
}
147145
return nil

accounts/abi/reflect.go

+8
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,11 @@ func set(dst, src reflect.Value, output Argument) error {
8585
}
8686
return nil
8787
}
88+
89+
// requireAssignable assures that `dest` is a pointer and it's not an interface.
90+
func requireAssignable(dst, src reflect.Value) error {
91+
if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface {
92+
return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type())
93+
}
94+
return nil
95+
}

accounts/abi/unpack.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,4 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err
202202

203203
//fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start)
204204
return
205-
}
205+
}

0 commit comments

Comments
 (0)