| 
									
										
										
										
											2018-02-14 13:49:11 +01:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package abi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | 	"encoding/hex" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	"math" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | // TestPack tests the general pack/unpack tests in packing_test.go | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | func TestPack(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | 	for i, test := range packUnpackTests { | 
					
						
							|  |  |  | 		t.Run(strconv.Itoa(i), func(t *testing.T) { | 
					
						
							|  |  |  | 			encb, err := hex.DecodeString(test.packed) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("invalid hex %s: %v", test.packed, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, test.def) | 
					
						
							|  |  |  | 			inAbi, err := JSON(strings.NewReader(inDef)) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("invalid ABI definition %s, %v", inDef, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			var packed []byte | 
					
						
							| 
									
										
										
										
											2020-09-28 14:10:26 +02:00
										 |  |  | 			packed, err = inAbi.Pack("method", test.unpacked) | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatalf("test %d (%v) failed: %v", i, test.def, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !reflect.DeepEqual(packed[4:], encb) { | 
					
						
							|  |  |  | 				t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, encb, packed[4:]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestMethodPack(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-04-27 15:07:33 +02:00
										 |  |  | 	abi, err := JSON(strings.NewReader(jsondata)) | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig := abi.Methods["slice"].ID | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packed, err := abi.Pack("slice", []uint32{1, 2}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Error(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var addrA, addrB = common.Address{1}, common.Address{2} | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["sliceAddress"].ID | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{32}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrA[:], 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrB[:], 32)...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packed, err = abi.Pack("sliceAddress", []common.Address{addrA, addrB}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var addrC, addrD = common.Address{3}, common.Address{4} | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["sliceMultiAddress"].ID | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{64}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{160}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrA[:], 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrB[:], 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrC[:], 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrD[:], 32)...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packed, err = abi.Pack("sliceMultiAddress", []common.Address{addrA, addrB}, []common.Address{addrC, addrD}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["slice256"].ID | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	packed, err = abi.Pack("slice256", []*big.Int{big.NewInt(1), big.NewInt(2)}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Error(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-10 16:59:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	a := [2][2]*big.Int{{big.NewInt(1), big.NewInt(1)}, {big.NewInt(2), big.NewInt(0)}} | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["nestedArray"].ID | 
					
						
							| 
									
										
										
										
											2019-01-10 16:59:37 +08:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0xa0}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrC[:], 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes(addrD[:], 32)...) | 
					
						
							|  |  |  | 	packed, err = abi.Pack("nestedArray", a, []common.Address{addrC, addrD}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["nestedArray2"].ID | 
					
						
							| 
									
										
										
										
											2019-01-10 16:59:37 +08:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x80}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	packed, err = abi.Pack("nestedArray2", [2][]uint8{{1}, {1}}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-20 09:01:04 +02:00
										 |  |  | 	sig = abi.Methods["nestedSlice"].ID | 
					
						
							| 
									
										
										
										
											2019-01-10 16:59:37 +08:00
										 |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x02}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{0xa0}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) | 
					
						
							|  |  |  | 	sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) | 
					
						
							|  |  |  | 	packed, err = abi.Pack("nestedSlice", [][]uint8{{1, 2}, {1, 2}}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !bytes.Equal(packed, sig) { | 
					
						
							|  |  |  | 		t.Errorf("expected %x got %x", sig, packed) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPackNumber(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		value  reflect.Value | 
					
						
							|  |  |  | 		packed []byte | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		// Protocol limits | 
					
						
							|  |  |  | 		{reflect.ValueOf(0), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(1), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(-1), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Type corner cases | 
					
						
							|  |  |  | 		{reflect.ValueOf(uint8(math.MaxUint8)), common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000ff")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(uint16(math.MaxUint16)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000ffff")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(uint32(math.MaxUint32)), common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000ffffffff")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(uint64(math.MaxUint64)), common.Hex2Bytes("000000000000000000000000000000000000000000000000ffffffffffffffff")}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{reflect.ValueOf(int8(math.MaxInt8)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000007f")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int16(math.MaxInt16)), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000007fff")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int32(math.MaxInt32)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000007fffffff")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int64(math.MaxInt64)), common.Hex2Bytes("0000000000000000000000000000000000000000000000007fffffffffffffff")}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{reflect.ValueOf(int8(math.MinInt8)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int16(math.MinInt16)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int32(math.MinInt32)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000")}, | 
					
						
							|  |  |  | 		{reflect.ValueOf(int64(math.MinInt64)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for i, tt := range tests { | 
					
						
							|  |  |  | 		packed := packNum(tt.value) | 
					
						
							|  |  |  | 		if !bytes.Equal(packed, tt.packed) { | 
					
						
							|  |  |  | 			t.Errorf("test %d: pack mismatch: have %x, want %x", i, packed, tt.packed) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |