Skip to content

Commit e32ee6a

Browse files
accounts/abi: added abi test cases, minor bug fixes (#20903)
* accounts/abi: added documentation * accounts/abi: reduced usage of arguments.LengthNonIndexed * accounts/abi: simplified reflection logic * accounts/abi: moved testjson data into global declaration * accounts/abi: removed duplicate test cases * accounts/abi: reworked abi tests * accounts/abi: added more tests for abi packing * accounts/abi/bind: refactored base tests * accounts/abi: run pack tests as subtests * accounts/abi: removed duplicate tests * accounts/abi: removed unnused arguments.LengthNonIndexed Due to refactors to the code, we do not need the arguments.LengthNonIndexed function anymore. You can still get the length by calling len(arguments.NonIndexed()) * accounts/abi: added type test * accounts/abi: modified unpack test to pack test * accounts/abi: length check on arrayTy * accounts/abi: test invalid abi * accounts/abi: fixed rebase error * accounts/abi: fixed rebase errors * accounts/abi: removed unused definition * accounts/abi: merged packing/unpacking tests * accounts/abi: fixed [][][32]bytes encoding * accounts/abi: added tuple test cases * accounts/abi: renamed getMockLog -> newMockLog * accounts/abi: removed duplicate test * accounts/abi: bools -> booleans
1 parent 40283d0 commit e32ee6a

File tree

10 files changed

+1323
-1188
lines changed

10 files changed

+1323
-1188
lines changed

accounts/abi/abi_test.go

Lines changed: 144 additions & 107 deletions
Large diffs are not rendered by default.

accounts/abi/argument.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,6 @@ func (argument *Argument) UnmarshalJSON(data []byte) error {
5959
return nil
6060
}
6161

62-
// LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events
63-
// can ever have 'indexed' arguments, it should always be false on arguments for method input/output
64-
func (arguments Arguments) LengthNonIndexed() int {
65-
out := 0
66-
for _, arg := range arguments {
67-
if !arg.Indexed {
68-
out++
69-
}
70-
}
71-
return out
72-
}
73-
7462
// NonIndexed returns the arguments with indexed arguments filtered out
7563
func (arguments Arguments) NonIndexed() Arguments {
7664
var ret []Argument
@@ -205,10 +193,11 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
205193

206194
// unpackAtomic unpacks ( hexdata -> go ) a single value
207195
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
208-
if arguments.LengthNonIndexed() == 0 {
196+
nonIndexedArgs := arguments.NonIndexed()
197+
if len(nonIndexedArgs) == 0 {
209198
return nil
210199
}
211-
argument := arguments.NonIndexed()[0]
200+
argument := nonIndexedArgs[0]
212201
elem := reflect.ValueOf(v).Elem()
213202

214203
if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
@@ -282,9 +271,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
282271
// without supplying a struct to unpack into. Instead, this method returns a list containing the
283272
// values. An atomic argument will be a list with one element.
284273
func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
285-
retval := make([]interface{}, 0, arguments.LengthNonIndexed())
274+
nonIndexedArgs := arguments.NonIndexed()
275+
retval := make([]interface{}, 0, len(nonIndexedArgs))
286276
virtualArgs := 0
287-
for index, arg := range arguments.NonIndexed() {
277+
for index, arg := range nonIndexedArgs {
288278
marshalledValue, err := ToGoType((index+virtualArgs)*32, arg.Type, data)
289279
if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
290280
// If we have a static array, like [3]uint256, these are coded as

accounts/abi/bind/base_test.go

Lines changed: 52 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
package bind_test
1818

1919
import (
20-
"bytes"
2120
"context"
2221
"math/big"
22+
"reflect"
2323
"strings"
2424
"testing"
2525

@@ -88,51 +88,23 @@ const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16
8888

8989
func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
9090
hash := crypto.Keccak256Hash([]byte("testName"))
91-
mockLog := types.Log{
92-
Address: common.HexToAddress("0x0"),
93-
Topics: []common.Hash{
94-
common.HexToHash("0x0"),
95-
hash,
96-
},
97-
Data: hexutil.MustDecode(hexData),
98-
BlockNumber: uint64(26),
99-
TxHash: common.HexToHash("0x0"),
100-
TxIndex: 111,
101-
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
102-
Index: 7,
103-
Removed: false,
91+
topics := []common.Hash{
92+
common.HexToHash("0x0"),
93+
hash,
10494
}
95+
mockLog := newMockLog(topics, common.HexToHash("0x0"))
10596

10697
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
10798
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
10899
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
109100

110-
receivedMap := make(map[string]interface{})
111101
expectedReceivedMap := map[string]interface{}{
112102
"name": hash,
113103
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
114104
"amount": big.NewInt(1),
115105
"memo": []byte{88},
116106
}
117-
if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil {
118-
t.Error(err)
119-
}
120-
121-
if len(receivedMap) != 4 {
122-
t.Fatal("unpacked map expected to have length 4")
123-
}
124-
if receivedMap["name"] != expectedReceivedMap["name"] {
125-
t.Error("unpacked map does not match expected map")
126-
}
127-
if receivedMap["sender"] != expectedReceivedMap["sender"] {
128-
t.Error("unpacked map does not match expected map")
129-
}
130-
if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
131-
t.Error("unpacked map does not match expected map")
132-
}
133-
if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
134-
t.Error("unpacked map does not match expected map")
135-
}
107+
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
136108
}
137109

138110
func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
@@ -141,51 +113,23 @@ func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
141113
t.Fatal(err)
142114
}
143115
hash := crypto.Keccak256Hash(sliceBytes)
144-
mockLog := types.Log{
145-
Address: common.HexToAddress("0x0"),
146-
Topics: []common.Hash{
147-
common.HexToHash("0x0"),
148-
hash,
149-
},
150-
Data: hexutil.MustDecode(hexData),
151-
BlockNumber: uint64(26),
152-
TxHash: common.HexToHash("0x0"),
153-
TxIndex: 111,
154-
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
155-
Index: 7,
156-
Removed: false,
116+
topics := []common.Hash{
117+
common.HexToHash("0x0"),
118+
hash,
157119
}
120+
mockLog := newMockLog(topics, common.HexToHash("0x0"))
158121

159122
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
160123
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
161124
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
162125

163-
receivedMap := make(map[string]interface{})
164126
expectedReceivedMap := map[string]interface{}{
165127
"names": hash,
166128
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
167129
"amount": big.NewInt(1),
168130
"memo": []byte{88},
169131
}
170-
if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil {
171-
t.Error(err)
172-
}
173-
174-
if len(receivedMap) != 4 {
175-
t.Fatal("unpacked map expected to have length 4")
176-
}
177-
if receivedMap["names"] != expectedReceivedMap["names"] {
178-
t.Error("unpacked map does not match expected map")
179-
}
180-
if receivedMap["sender"] != expectedReceivedMap["sender"] {
181-
t.Error("unpacked map does not match expected map")
182-
}
183-
if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
184-
t.Error("unpacked map does not match expected map")
185-
}
186-
if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
187-
t.Error("unpacked map does not match expected map")
188-
}
132+
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
189133
}
190134

191135
func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
@@ -194,51 +138,23 @@ func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
194138
t.Fatal(err)
195139
}
196140
hash := crypto.Keccak256Hash(arrBytes)
197-
mockLog := types.Log{
198-
Address: common.HexToAddress("0x0"),
199-
Topics: []common.Hash{
200-
common.HexToHash("0x0"),
201-
hash,
202-
},
203-
Data: hexutil.MustDecode(hexData),
204-
BlockNumber: uint64(26),
205-
TxHash: common.HexToHash("0x0"),
206-
TxIndex: 111,
207-
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
208-
Index: 7,
209-
Removed: false,
141+
topics := []common.Hash{
142+
common.HexToHash("0x0"),
143+
hash,
210144
}
145+
mockLog := newMockLog(topics, common.HexToHash("0x0"))
211146

212147
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
213148
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
214149
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
215150

216-
receivedMap := make(map[string]interface{})
217151
expectedReceivedMap := map[string]interface{}{
218152
"addresses": hash,
219153
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
220154
"amount": big.NewInt(1),
221155
"memo": []byte{88},
222156
}
223-
if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil {
224-
t.Error(err)
225-
}
226-
227-
if len(receivedMap) != 4 {
228-
t.Fatal("unpacked map expected to have length 4")
229-
}
230-
if receivedMap["addresses"] != expectedReceivedMap["addresses"] {
231-
t.Error("unpacked map does not match expected map")
232-
}
233-
if receivedMap["sender"] != expectedReceivedMap["sender"] {
234-
t.Error("unpacked map does not match expected map")
235-
}
236-
if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
237-
t.Error("unpacked map does not match expected map")
238-
}
239-
if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
240-
t.Error("unpacked map does not match expected map")
241-
}
157+
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
242158
}
243159

244160
func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
@@ -249,99 +165,72 @@ func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
249165
functionTyBytes := append(addrBytes, functionSelector...)
250166
var functionTy [24]byte
251167
copy(functionTy[:], functionTyBytes[0:24])
252-
mockLog := types.Log{
253-
Address: common.HexToAddress("0x0"),
254-
Topics: []common.Hash{
255-
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
256-
common.BytesToHash(functionTyBytes),
257-
},
258-
Data: hexutil.MustDecode(hexData),
259-
BlockNumber: uint64(26),
260-
TxHash: common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"),
261-
TxIndex: 111,
262-
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
263-
Index: 7,
264-
Removed: false,
168+
topics := []common.Hash{
169+
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
170+
common.BytesToHash(functionTyBytes),
265171
}
266-
172+
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
267173
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
268174
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
269175
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
270176

271-
receivedMap := make(map[string]interface{})
272177
expectedReceivedMap := map[string]interface{}{
273178
"function": functionTy,
274179
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
275180
"amount": big.NewInt(1),
276181
"memo": []byte{88},
277182
}
278-
if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil {
279-
t.Error(err)
280-
}
281-
282-
if len(receivedMap) != 4 {
283-
t.Fatal("unpacked map expected to have length 4")
284-
}
285-
if receivedMap["function"] != expectedReceivedMap["function"] {
286-
t.Error("unpacked map does not match expected map")
287-
}
288-
if receivedMap["sender"] != expectedReceivedMap["sender"] {
289-
t.Error("unpacked map does not match expected map")
290-
}
291-
if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
292-
t.Error("unpacked map does not match expected map")
293-
}
294-
if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
295-
t.Error("unpacked map does not match expected map")
296-
}
183+
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
297184
}
298185

299186
func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
300-
byts := []byte{1, 2, 3, 4, 5}
301-
hash := crypto.Keccak256Hash(byts)
302-
mockLog := types.Log{
303-
Address: common.HexToAddress("0x0"),
304-
Topics: []common.Hash{
305-
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
306-
hash,
307-
},
308-
Data: hexutil.MustDecode(hexData),
309-
BlockNumber: uint64(26),
310-
TxHash: common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"),
311-
TxIndex: 111,
312-
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
313-
Index: 7,
314-
Removed: false,
187+
bytes := []byte{1, 2, 3, 4, 5}
188+
hash := crypto.Keccak256Hash(bytes)
189+
topics := []common.Hash{
190+
common.HexToHash("0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"),
191+
hash,
315192
}
193+
mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42"))
316194

317195
abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
318196
parsedAbi, _ := abi.JSON(strings.NewReader(abiString))
319197
bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil)
320198

321-
receivedMap := make(map[string]interface{})
322199
expectedReceivedMap := map[string]interface{}{
323200
"content": hash,
324201
"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
325202
"amount": big.NewInt(1),
326203
"memo": []byte{88},
327204
}
328-
if err := bc.UnpackLogIntoMap(receivedMap, "received", mockLog); err != nil {
205+
unpackAndCheck(t, bc, expectedReceivedMap, mockLog)
206+
}
207+
208+
func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) {
209+
received := make(map[string]interface{})
210+
if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil {
329211
t.Error(err)
330212
}
331213

332-
if len(receivedMap) != 4 {
333-
t.Fatal("unpacked map expected to have length 4")
214+
if len(received) != len(expected) {
215+
t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected))
334216
}
335-
if receivedMap["content"] != expectedReceivedMap["content"] {
336-
t.Error("unpacked map does not match expected map")
217+
for name, elem := range expected {
218+
if !reflect.DeepEqual(elem, received[name]) {
219+
t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name])
220+
}
337221
}
338-
if receivedMap["sender"] != expectedReceivedMap["sender"] {
339-
t.Error("unpacked map does not match expected map")
340-
}
341-
if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
342-
t.Error("unpacked map does not match expected map")
343-
}
344-
if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
345-
t.Error("unpacked map does not match expected map")
222+
}
223+
224+
func newMockLog(topics []common.Hash, txHash common.Hash) types.Log {
225+
return types.Log{
226+
Address: common.HexToAddress("0x0"),
227+
Topics: topics,
228+
Data: hexutil.MustDecode(hexData),
229+
BlockNumber: uint64(26),
230+
TxHash: txHash,
231+
TxIndex: 111,
232+
BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}),
233+
Index: 7,
234+
Removed: false,
346235
}
347236
}

accounts/abi/error.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
4646
return typeErr(formatSliceString(t.Elem.Kind, t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
4747
}
4848

49-
if t.Elem.T == SliceTy {
49+
if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
5050
if val.Len() > 0 {
5151
return sliceTypeCheck(*t.Elem, val.Index(0))
5252
}
53-
} else if t.Elem.T == ArrayTy {
54-
return sliceTypeCheck(*t.Elem, val.Index(0))
5553
}
5654

5755
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Kind {

accounts/abi/numbers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var (
3939
)
4040

4141
// U256 converts a big Int into a 256bit EVM number.
42+
// This operation is destructive.
4243
func U256(n *big.Int) []byte {
4344
return math.PaddedBigBytes(math.U256(n), 32)
4445
}

0 commit comments

Comments
 (0)