@@ -67,28 +67,43 @@ func (arguments Arguments) LengthNonIndexed() int {
6767 return out
6868}
6969
70+ // NonIndexed returns the arguments with indexed arguments filtered out
71+ func (arguments Arguments ) NonIndexed () Arguments {
72+ var ret []Argument
73+ for _ , arg := range arguments {
74+ if ! arg .Indexed {
75+ ret = append (ret , arg )
76+ }
77+ }
78+ return ret
79+ }
80+
7081// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
7182func (arguments Arguments ) isTuple () bool {
7283 return len (arguments ) > 1
7384}
7485
7586// Unpack performs the operation hexdata -> Go format
7687func (arguments Arguments ) Unpack (v interface {}, data []byte ) error {
77- if arguments .isTuple () {
78- return arguments .unpackTuple (v , data )
79- }
80- return arguments .unpackAtomic (v , data )
81- }
8288
83- func (arguments Arguments ) unpackTuple (v interface {}, output []byte ) error {
8489 // make sure the passed value is arguments pointer
85- valueOf := reflect .ValueOf (v )
86- if reflect .Ptr != valueOf .Kind () {
90+ if reflect .Ptr != reflect .ValueOf (v ).Kind () {
8791 return fmt .Errorf ("abi: Unpack(non-pointer %T)" , v )
8892 }
93+ marshalledValues , err := arguments .UnpackValues (data )
94+ if err != nil {
95+ return err
96+ }
97+ if arguments .isTuple () {
98+ return arguments .unpackTuple (v , marshalledValues )
99+ }
100+ return arguments .unpackAtomic (v , marshalledValues )
101+ }
102+
103+ func (arguments Arguments ) unpackTuple (v interface {}, marshalledValues []interface {}) error {
89104
90105 var (
91- value = valueOf .Elem ()
106+ value = reflect . ValueOf ( v ) .Elem ()
92107 typ = value .Type ()
93108 kind = value .Kind ()
94109 )
@@ -110,30 +125,9 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
110125 exists [field ] = true
111126 }
112127 }
113- // `i` counts the nonindexed arguments.
114- // `j` counts the number of complex types.
115- // both `i` and `j` are used to to correctly compute `data` offset.
128+ for i , arg := range arguments .NonIndexed () {
116129
117- i , j := - 1 , 0
118- for _ , arg := range arguments {
119-
120- if arg .Indexed {
121- // can't read, continue
122- continue
123- }
124- i ++
125- marshalledValue , err := toGoType ((i + j )* 32 , arg .Type , output )
126- if err != nil {
127- return err
128- }
129-
130- if arg .Type .T == ArrayTy {
131- // combined index ('i' + 'j') need to be adjusted only by size of array, thus
132- // we need to decrement 'j' because 'i' was incremented
133- j += arg .Type .Size - 1
134- }
135-
136- reflectValue := reflect .ValueOf (marshalledValue )
130+ reflectValue := reflect .ValueOf (marshalledValues [i ])
137131
138132 switch kind {
139133 case reflect .Struct :
@@ -166,34 +160,52 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
166160}
167161
168162// unpackAtomic unpacks ( hexdata -> go ) a single value
169- func (arguments Arguments ) unpackAtomic (v interface {}, output []byte ) error {
170- // make sure the passed value is arguments pointer
171- valueOf := reflect .ValueOf (v )
172- if reflect .Ptr != valueOf .Kind () {
173- return fmt .Errorf ("abi: Unpack(non-pointer %T)" , v )
174- }
175- arg := arguments [0 ]
176- if arg .Indexed {
177- return fmt .Errorf ("abi: attempting to unpack indexed variable into element." )
163+ func (arguments Arguments ) unpackAtomic (v interface {}, marshalledValues []interface {}) error {
164+ if len (marshalledValues ) != 1 {
165+ return fmt .Errorf ("abi: wrong length, expected single value, got %d" , len (marshalledValues ))
178166 }
167+ elem := reflect .ValueOf (v ).Elem ()
168+ reflectValue := reflect .ValueOf (marshalledValues [0 ])
169+ return set (elem , reflectValue , arguments .NonIndexed ()[0 ])
170+ }
179171
180- value := valueOf .Elem ()
172+ // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
173+ // without supplying a struct to unpack into. Instead, this method returns a list containing the
174+ // values. An atomic argument will be a list with one element.
175+ func (arguments Arguments ) UnpackValues (data []byte ) ([]interface {}, error ) {
176+ retval := make ([]interface {}, 0 , arguments .LengthNonIndexed ())
177+ virtualArgs := 0
178+ for index , arg := range arguments .NonIndexed () {
179+ marshalledValue , err := toGoType ((index + virtualArgs )* 32 , arg .Type , data )
180+ if arg .Type .T == ArrayTy {
181+ // If we have a static array, like [3]uint256, these are coded as
182+ // just like uint256,uint256,uint256.
183+ // This means that we need to add two 'virtual' arguments when
184+ // we count the index from now on
181185
182- marshalledValue , err := toGoType (0 , arg .Type , output )
183- if err != nil {
184- return err
186+ virtualArgs += arg .Type .Size - 1
187+ }
188+ if err != nil {
189+ return nil , err
190+ }
191+ retval = append (retval , marshalledValue )
185192 }
186- return set ( value , reflect . ValueOf ( marshalledValue ), arg )
193+ return retval , nil
187194}
188195
189- // Unpack performs the operation Go format -> Hexdata
196+ // PackValues performs the operation Go format -> Hexdata
197+ // It is the semantic opposite of UnpackValues
198+ func (arguments Arguments ) PackValues (args []interface {}) ([]byte , error ) {
199+ return arguments .Pack (args ... )
200+ }
201+
202+ // Pack performs the operation Go format -> Hexdata
190203func (arguments Arguments ) Pack (args ... interface {}) ([]byte , error ) {
191204 // Make sure arguments match up and pack them
192205 abiArgs := arguments
193206 if len (args ) != len (abiArgs ) {
194207 return nil , fmt .Errorf ("argument count mismatch: %d for %d" , len (args ), len (abiArgs ))
195208 }
196-
197209 // variable input is the output appended at the end of packed
198210 // output. This is used for strings and bytes types input.
199211 var variableInput []byte
@@ -207,7 +219,6 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
207219 inputOffset += 32
208220 }
209221 }
210-
211222 var ret []byte
212223 for i , a := range args {
213224 input := abiArgs [i ]
@@ -216,7 +227,6 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
216227 if err != nil {
217228 return nil , err
218229 }
219-
220230 // check for a slice type (string, bytes, slice)
221231 if input .Type .requiresLengthPrefix () {
222232 // calculate the offset
0 commit comments