@@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
238238 return fmt .Errorf ("abi: unmarshalling empty output" )
239239 }
240240
241- value := reflect .ValueOf (v ).Elem ()
242- typ := value .Type ()
241+ // make sure the passed value is a pointer
242+ valueOf := reflect .ValueOf (v )
243+ if reflect .Ptr != valueOf .Kind () {
244+ return fmt .Errorf ("abi: Unpack(non-pointer %T)" , v )
245+ }
246+
247+ var (
248+ value = valueOf .Elem ()
249+ typ = value .Type ()
250+ )
243251
244252 if len (method .Outputs ) > 1 {
245253 switch value .Kind () {
@@ -268,6 +276,25 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
268276 return fmt .Errorf ("abi: cannot marshal tuple in to slice %T (only []interface{} is supported)" , v )
269277 }
270278
279+ // if the slice already contains values, set those instead of the interface slice itself.
280+ if value .Len () > 0 {
281+ if len (method .Outputs ) > value .Len () {
282+ return fmt .Errorf ("abi: cannot marshal in to slices of unequal size (require: %v, got: %v)" , len (method .Outputs ), value .Len ())
283+ }
284+
285+ for i := 0 ; i < len (method .Outputs ); i ++ {
286+ marshalledValue , err := toGoType (i , method .Outputs [i ], output )
287+ if err != nil {
288+ return err
289+ }
290+ reflectValue := reflect .ValueOf (marshalledValue )
291+ if err := set (value .Index (i ).Elem (), reflectValue , method .Outputs [i ]); err != nil {
292+ return err
293+ }
294+ }
295+ return nil
296+ }
297+
271298 // create a new slice and start appending the unmarshalled
272299 // values to the new interface slice.
273300 z := reflect .MakeSlice (typ , 0 , len (method .Outputs ))
@@ -296,34 +323,6 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
296323 return nil
297324}
298325
299- // set attempts to assign src to dst by either setting, copying or otherwise.
300- //
301- // set is a bit more lenient when it comes to assignment and doesn't force an as
302- // strict ruleset as bare `reflect` does.
303- func set (dst , src reflect.Value , output Argument ) error {
304- dstType := dst .Type ()
305- srcType := src .Type ()
306-
307- switch {
308- case dstType .AssignableTo (src .Type ()):
309- dst .Set (src )
310- case dstType .Kind () == reflect .Array && srcType .Kind () == reflect .Slice :
311- if ! dstType .Elem ().AssignableTo (r_byte ) {
312- return fmt .Errorf ("abi: cannot unmarshal %v in to array of elem %v" , src .Type (), dstType .Elem ())
313- }
314-
315- if dst .Len () < output .Type .SliceSize {
316- return fmt .Errorf ("abi: cannot unmarshal src (len=%d) in to dst (len=%d)" , output .Type .SliceSize , dst .Len ())
317- }
318- reflect .Copy (dst , src )
319- case dstType .Kind () == reflect .Interface :
320- dst .Set (src )
321- default :
322- return fmt .Errorf ("abi: cannot unmarshal %v in to %v" , src .Type (), dst .Type ())
323- }
324- return nil
325- }
326-
327326func (abi * ABI ) UnmarshalJSON (data []byte ) error {
328327 var fields []struct {
329328 Type string
0 commit comments