Bläddra i källkod

accounts/abi: ABI explicit difference between Unpack and UnpackIntoInterface (#21091)

* accounts/abi: refactored abi.Unpack

* accounts/abi/bind: fixed error

* accounts/abi/bind: modified template

* accounts/abi/bind: added ToStruct for conversion

* accounts/abi: reenabled tests

* accounts/abi: fixed tests

* accounts/abi: fixed tests for packing/unpacking

* accounts/abi: fixed tests

* accounts/abi: added more logic to ToStruct

* accounts/abi/bind: fixed template

* accounts/abi/bind: fixed ToStruct conversion

* accounts/abi/: removed unused code

* accounts/abi: updated template

* accounts/abi: refactored unused code

* contracts/checkpointoracle: updated contracts to sol ^0.6.0

* accounts/abi: refactored reflection logic

* accounts/abi: less code duplication in Unpack*

* accounts/abi: fixed rebasing bug

* fix a few typos in comments

* rebase on master

Co-authored-by: Guillaume Ballet <gballet@gmail.com>
Marius van der Wijden 5 år sedan
förälder
incheckning
420b78659b

+ 40 - 20
accounts/abi/abi.go

@@ -80,36 +80,56 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
 	return append(method.ID, arguments...), nil
 }
 
-// Unpack output in v according to the abi specification.
-func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
+func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
 	// since there can't be naming collisions with contracts and events,
 	// we need to decide whether we're calling a method or an event
+	var args Arguments
 	if method, ok := abi.Methods[name]; ok {
 		if len(data)%32 != 0 {
-			return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
+			return nil, fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
 		}
-		return method.Outputs.Unpack(v, data)
+		args = method.Outputs
 	}
 	if event, ok := abi.Events[name]; ok {
-		return event.Inputs.Unpack(v, data)
+		args = event.Inputs
 	}
-	return fmt.Errorf("abi: could not locate named method or event")
+	if args == nil {
+		return nil, errors.New("abi: could not locate named method or event")
+	}
+	return args, nil
+}
+
+// Unpack unpacks the output according to the abi specification.
+func (abi ABI) Unpack(name string, data []byte) ([]interface{}, error) {
+	args, err := abi.getArguments(name, data)
+	if err != nil {
+		return nil, err
+	}
+	return args.Unpack(data)
+}
+
+// UnpackIntoInterface unpacks the output in v according to the abi specification.
+// It performs an additional copy. Please only use, if you want to unpack into a
+// structure that does not strictly conform to the abi structure (e.g. has additional arguments)
+func (abi ABI) UnpackIntoInterface(v interface{}, name string, data []byte) error {
+	args, err := abi.getArguments(name, data)
+	if err != nil {
+		return err
+	}
+	unpacked, err := args.Unpack(data)
+	if err != nil {
+		return err
+	}
+	return args.Copy(v, unpacked)
 }
 
 // UnpackIntoMap unpacks a log into the provided map[string]interface{}.
 func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
-	// since there can't be naming collisions with contracts and events,
-	// we need to decide whether we're calling a method or an event
-	if method, ok := abi.Methods[name]; ok {
-		if len(data)%32 != 0 {
-			return fmt.Errorf("abi: improperly formatted output")
-		}
-		return method.Outputs.UnpackIntoMap(v, data)
-	}
-	if event, ok := abi.Events[name]; ok {
-		return event.Inputs.UnpackIntoMap(v, data)
+	args, err := abi.getArguments(name, data)
+	if err != nil {
+		return err
 	}
-	return fmt.Errorf("abi: could not locate named method or event")
+	return args.UnpackIntoMap(v, data)
 }
 
 // UnmarshalJSON implements json.Unmarshaler interface.
@@ -250,10 +270,10 @@ func UnpackRevert(data []byte) (string, error) {
 	if !bytes.Equal(data[:4], revertSelector) {
 		return "", errors.New("invalid data for unpacking")
 	}
-	var reason string
 	typ, _ := NewType("string", "", nil)
-	if err := (Arguments{{Type: typ}}).Unpack(&reason, data[4:]); err != nil {
+	unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
+	if err != nil {
 		return "", err
 	}
-	return reason, nil
+	return unpacked[0].(string), nil
 }

+ 7 - 10
accounts/abi/abi_test.go

@@ -181,18 +181,15 @@ func TestConstructor(t *testing.T) {
 	if err != nil {
 		t.Error(err)
 	}
-	v := struct {
-		A *big.Int
-		B *big.Int
-	}{new(big.Int), new(big.Int)}
-	//abi.Unpack(&v, "", packed)
-	if err := abi.Constructor.Inputs.Unpack(&v, packed); err != nil {
+	unpacked, err := abi.Constructor.Inputs.Unpack(packed)
+	if err != nil {
 		t.Error(err)
 	}
-	if !reflect.DeepEqual(v.A, big.NewInt(1)) {
+
+	if !reflect.DeepEqual(unpacked[0], big.NewInt(1)) {
 		t.Error("Unable to pack/unpack from constructor")
 	}
-	if !reflect.DeepEqual(v.B, big.NewInt(2)) {
+	if !reflect.DeepEqual(unpacked[1], big.NewInt(2)) {
 		t.Error("Unable to pack/unpack from constructor")
 	}
 }
@@ -743,7 +740,7 @@ func TestUnpackEvent(t *testing.T) {
 	}
 	var ev ReceivedEvent
 
-	err = abi.Unpack(&ev, "received", data)
+	err = abi.UnpackIntoInterface(&ev, "received", data)
 	if err != nil {
 		t.Error(err)
 	}
@@ -752,7 +749,7 @@ func TestUnpackEvent(t *testing.T) {
 		Sender common.Address
 	}
 	var receivedAddrEv ReceivedAddrEvent
-	err = abi.Unpack(&receivedAddrEv, "receivedAddr", data)
+	err = abi.UnpackIntoInterface(&receivedAddrEv, "receivedAddr", data)
 	if err != nil {
 		t.Error(err)
 	}

+ 32 - 22
accounts/abi/argument.go

@@ -76,28 +76,20 @@ func (arguments Arguments) isTuple() bool {
 }
 
 // Unpack performs the operation hexdata -> Go format.
-func (arguments Arguments) Unpack(v interface{}, data []byte) error {
+func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
 	if len(data) == 0 {
 		if len(arguments) != 0 {
-			return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
+			return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
 		}
-		return nil // Nothing to unmarshal, return
-	}
-	// make sure the passed value is arguments pointer
-	if reflect.Ptr != reflect.ValueOf(v).Kind() {
-		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
-	}
-	marshalledValues, err := arguments.UnpackValues(data)
-	if err != nil {
-		return err
-	}
-	if len(marshalledValues) == 0 {
-		return fmt.Errorf("abi: Unpack(no-values unmarshalled %T)", v)
-	}
-	if arguments.isTuple() {
-		return arguments.unpackTuple(v, marshalledValues)
+		// Nothing to unmarshal, return default variables
+		nonIndexedArgs := arguments.NonIndexed()
+		defaultVars := make([]interface{}, len(nonIndexedArgs))
+		for index, arg := range nonIndexedArgs {
+			defaultVars[index] = reflect.New(arg.Type.GetType())
+		}
+		return defaultVars, nil
 	}
-	return arguments.unpackAtomic(v, marshalledValues[0])
+	return arguments.UnpackValues(data)
 }
 
 // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value.
@@ -122,8 +114,26 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
 	return nil
 }
 
-// unpackAtomic unpacks ( hexdata -> go ) a single value.
-func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
+// Copy performs the operation go format -> provided struct.
+func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
+	// make sure the passed value is arguments pointer
+	if reflect.Ptr != reflect.ValueOf(v).Kind() {
+		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
+	}
+	if len(values) == 0 {
+		if len(arguments) != 0 {
+			return fmt.Errorf("abi: attempting to copy no values while %d arguments are expected", len(arguments))
+		}
+		return nil // Nothing to copy, return
+	}
+	if arguments.isTuple() {
+		return arguments.copyTuple(v, values)
+	}
+	return arguments.copyAtomic(v, values[0])
+}
+
+// unpackAtomic unpacks ( hexdata -> go ) a single value
+func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error {
 	dst := reflect.ValueOf(v).Elem()
 	src := reflect.ValueOf(marshalledValues)
 
@@ -133,8 +143,8 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interfac
 	return set(dst, src)
 }
 
-// unpackTuple unpacks ( hexdata -> go ) a batch of values.
-func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
+// copyTuple copies a batch of values from marshalledValues to v.
+func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error {
 	value := reflect.ValueOf(v).Elem()
 	nonIndexedArgs := arguments.NonIndexed()
 

+ 11 - 4
accounts/abi/bind/base.go

@@ -117,11 +117,14 @@ func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend Co
 // sets the output to result. The result type might be a single field for simple
 // returns, a slice of interfaces for anonymous returns and a struct for named
 // returns.
-func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string, params ...interface{}) error {
+func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method string, params ...interface{}) error {
 	// Don't crash on a lazy user
 	if opts == nil {
 		opts = new(CallOpts)
 	}
+	if results == nil {
+		results = new([]interface{})
+	}
 	// Pack the input, call and unpack the results
 	input, err := c.abi.Pack(method, params...)
 	if err != nil {
@@ -158,10 +161,14 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
 			}
 		}
 	}
-	if err != nil {
+
+	if len(*results) == 0 {
+		res, err := c.abi.Unpack(method, output)
+		*results = res
 		return err
 	}
-	return c.abi.Unpack(result, method, output)
+	res := *results
+	return c.abi.UnpackIntoInterface(res[0], method, output)
 }
 
 // Transact invokes the (paid) contract method with params as input values.
@@ -339,7 +346,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
 // UnpackLog unpacks a retrieved log into the provided output structure.
 func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
 	if len(log.Data) > 0 {
-		if err := c.abi.Unpack(out, event, log.Data); err != nil {
+		if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
 			return err
 		}
 	}

+ 3 - 4
accounts/abi/bind/base_test.go

@@ -71,11 +71,10 @@ func TestPassingBlockNumber(t *testing.T) {
 			},
 		},
 	}, mc, nil, nil)
-	var ret string
 
 	blockNumber := big.NewInt(42)
 
-	bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, &ret, "something")
+	bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something")
 
 	if mc.callContractBlockNumber != blockNumber {
 		t.Fatalf("CallContract() was not passed the block number")
@@ -85,7 +84,7 @@ func TestPassingBlockNumber(t *testing.T) {
 		t.Fatalf("CodeAt() was not passed the block number")
 	}
 
-	bc.Call(&bind.CallOpts{}, &ret, "something")
+	bc.Call(&bind.CallOpts{}, nil, "something")
 
 	if mc.callContractBlockNumber != nil {
 		t.Fatalf("CallContract() was passed a block number when it should not have been")
@@ -95,7 +94,7 @@ func TestPassingBlockNumber(t *testing.T) {
 		t.Fatalf("CodeAt() was passed a block number when it should not have been")
 	}
 
-	bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, &ret, "something")
+	bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something")
 
 	if !mc.pendingCallContractCalled {
 		t.Fatalf("CallContract() was not passed the block number")

+ 2 - 2
accounts/abi/bind/bind_test.go

@@ -1696,11 +1696,11 @@ func TestGolangBindings(t *testing.T) {
 		t.Skip("go sdk not found for testing")
 	}
 	// Create a temporary workspace for the test suite
-	ws, err := ioutil.TempDir("", "")
+	ws, err := ioutil.TempDir("", "binding-test")
 	if err != nil {
 		t.Fatalf("failed to create temporary workspace: %v", err)
 	}
-	defer os.RemoveAll(ws)
+	//defer os.RemoveAll(ws)
 
 	pkg := filepath.Join(ws, "bindtest")
 	if err = os.MkdirAll(pkg, 0700); err != nil {

+ 19 - 15
accounts/abi/bind/template.go

@@ -261,7 +261,7 @@ var (
 	// sets the output to result. The result type might be a single field for simple
 	// returns, a slice of interfaces for anonymous returns and a struct for named
 	// returns.
-	func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+	func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
 		return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.contract.Call(opts, result, method, params...)
 	}
 
@@ -280,7 +280,7 @@ var (
 	// sets the output to result. The result type might be a single field for simple
 	// returns, a slice of interfaces for anonymous returns and a struct for named
 	// returns.
-	func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+	func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
 		return _{{$contract.Type}}.Contract.contract.Call(opts, result, method, params...)
 	}
 
@@ -300,19 +300,23 @@ var (
 		//
 		// Solidity: {{.Original.String}}
 		func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
-			{{if .Structured}}ret := new(struct{
-				{{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}}
-				{{end}}
-			}){{else}}var (
-				{{range $i, $_ := .Normalized.Outputs}}ret{{$i}} = new({{bindtype .Type $structs}})
-				{{end}}
-			){{end}}
-			out := {{if .Structured}}ret{{else}}{{if eq (len .Normalized.Outputs) 1}}ret0{{else}}&[]interface{}{
-				{{range $i, $_ := .Normalized.Outputs}}ret{{$i}},
-				{{end}}
-			}{{end}}{{end}}
-			err := _{{$contract.Type}}.contract.Call(opts, out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
-			return {{if .Structured}}*ret,{{else}}{{range $i, $_ := .Normalized.Outputs}}*ret{{$i}},{{end}}{{end}} err
+			var out []interface{}
+			err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
+			{{if .Structured}}
+			outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} })
+			{{range $i, $t := .Normalized.Outputs}} 
+			outstruct.{{.Name}} = out[{{$i}}].({{bindtype .Type $structs}}){{end}}
+
+			return *outstruct, err
+			{{else}}
+			if err != nil {
+				return {{range $i, $_ := .Normalized.Outputs}}*new({{bindtype .Type $structs}}), {{end}} err
+			}
+			{{range $i, $t := .Normalized.Outputs}}
+			out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
+			
+			return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
+			{{end}}
 		}
 
 		// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.

+ 9 - 13
accounts/abi/event_test.go

@@ -147,10 +147,6 @@ func TestEventString(t *testing.T) {
 // TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
 func TestEventMultiValueWithArrayUnpack(t *testing.T) {
 	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
-	type testStruct struct {
-		Value1 [2]uint8
-		Value2 uint8
-	}
 	abi, err := JSON(strings.NewReader(definition))
 	require.NoError(t, err)
 	var b bytes.Buffer
@@ -158,10 +154,10 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
 	for ; i <= 3; i++ {
 		b.Write(packNum(reflect.ValueOf(i)))
 	}
-	var rst testStruct
-	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
-	require.Equal(t, [2]uint8{1, 2}, rst.Value1)
-	require.Equal(t, uint8(3), rst.Value2)
+	unpacked, err := abi.Unpack("test", b.Bytes())
+	require.NoError(t, err)
+	require.Equal(t, [2]uint8{1, 2}, unpacked[0])
+	require.Equal(t, uint8(3), unpacked[1])
 }
 
 func TestEventTupleUnpack(t *testing.T) {
@@ -351,14 +347,14 @@ func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, ass
 	var e Event
 	assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI")
 	a := ABI{Events: map[string]Event{"e": e}}
-	return a.Unpack(dest, "e", data)
+	return a.UnpackIntoInterface(dest, "e", data)
 }
 
 // TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
 func TestEventUnpackIndexed(t *testing.T) {
 	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
 	type testStruct struct {
-		Value1 uint8
+		Value1 uint8 // indexed
 		Value2 uint8
 	}
 	abi, err := JSON(strings.NewReader(definition))
@@ -366,7 +362,7 @@ func TestEventUnpackIndexed(t *testing.T) {
 	var b bytes.Buffer
 	b.Write(packNum(reflect.ValueOf(uint8(8))))
 	var rst testStruct
-	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
+	require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes()))
 	require.Equal(t, uint8(0), rst.Value1)
 	require.Equal(t, uint8(8), rst.Value2)
 }
@@ -375,7 +371,7 @@ func TestEventUnpackIndexed(t *testing.T) {
 func TestEventIndexedWithArrayUnpack(t *testing.T) {
 	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
 	type testStruct struct {
-		Value1 [2]uint8
+		Value1 [2]uint8 // indexed
 		Value2 string
 	}
 	abi, err := JSON(strings.NewReader(definition))
@@ -388,7 +384,7 @@ func TestEventIndexedWithArrayUnpack(t *testing.T) {
 	b.Write(common.RightPadBytes([]byte(stringOut), 32))
 
 	var rst testStruct
-	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
+	require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes()))
 	require.Equal(t, [2]uint8{0, 0}, rst.Value1)
 	require.Equal(t, stringOut, rst.Value2)
 }

+ 1 - 12
accounts/abi/pack_test.go

@@ -44,18 +44,7 @@ func TestPack(t *testing.T) {
 				t.Fatalf("invalid ABI definition %s, %v", inDef, err)
 			}
 			var packed []byte
-			if reflect.TypeOf(test.unpacked).Kind() != reflect.Struct {
-				packed, err = inAbi.Pack("method", test.unpacked)
-			} else {
-				// if want is a struct we need to use the components.
-				elem := reflect.ValueOf(test.unpacked)
-				var values []interface{}
-				for i := 0; i < elem.NumField(); i++ {
-					field := elem.Field(i)
-					values = append(values, field.Interface())
-				}
-				packed, err = inAbi.Pack("method", values...)
-			}
+			packed, err = inAbi.Pack("method", test.unpacked)
 
 			if err != nil {
 				t.Fatalf("test %d (%v) failed: %v", i, test.def, err)

+ 26 - 24
accounts/abi/packing_test.go

@@ -620,7 +620,7 @@ var packUnpackTests = []packUnpackTest{
 
 	{
 		def:      `[{"type": "bytes32[]"}]`,
-		unpacked: []common.Hash{{1}, {2}},
+		unpacked: [][32]byte{{1}, {2}},
 		packed: "0000000000000000000000000000000000000000000000000000000000000020" +
 			"0000000000000000000000000000000000000000000000000000000000000002" +
 			"0100000000000000000000000000000000000000000000000000000000000000" +
@@ -722,7 +722,7 @@ var packUnpackTests = []packUnpackTest{
 	},
 	// struct outputs
 	{
-		def: `[{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}]`,
+		def: `[{"components": [{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}], "type":"tuple"}]`,
 		packed: "0000000000000000000000000000000000000000000000000000000000000001" +
 			"0000000000000000000000000000000000000000000000000000000000000002",
 		unpacked: struct {
@@ -731,28 +731,28 @@ var packUnpackTests = []packUnpackTest{
 		}{big.NewInt(1), big.NewInt(2)},
 	},
 	{
-		def:    `[{"name":"int_one","type":"int256"}]`,
+		def:    `[{"components": [{"name":"int_one","type":"int256"}], "type":"tuple"}]`,
 		packed: "0000000000000000000000000000000000000000000000000000000000000001",
 		unpacked: struct {
 			IntOne *big.Int
 		}{big.NewInt(1)},
 	},
 	{
-		def:    `[{"name":"int__one","type":"int256"}]`,
+		def:    `[{"components": [{"name":"int__one","type":"int256"}], "type":"tuple"}]`,
 		packed: "0000000000000000000000000000000000000000000000000000000000000001",
 		unpacked: struct {
 			IntOne *big.Int
 		}{big.NewInt(1)},
 	},
 	{
-		def:    `[{"name":"int_one_","type":"int256"}]`,
+		def:    `[{"components": [{"name":"int_one_","type":"int256"}], "type":"tuple"}]`,
 		packed: "0000000000000000000000000000000000000000000000000000000000000001",
 		unpacked: struct {
 			IntOne *big.Int
 		}{big.NewInt(1)},
 	},
 	{
-		def: `[{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}]`,
+		def: `[{"components": [{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}], "type":"tuple"}]`,
 		packed: "0000000000000000000000000000000000000000000000000000000000000001" +
 			"0000000000000000000000000000000000000000000000000000000000000002",
 		unpacked: struct {
@@ -831,11 +831,11 @@ var packUnpackTests = []packUnpackTest{
 	},
 	{
 		// static tuple
-		def: `[{"name":"a","type":"int64"}, 
+		def: `[{"components": [{"name":"a","type":"int64"}, 
 		{"name":"b","type":"int256"}, 
 		{"name":"c","type":"int256"}, 
 		{"name":"d","type":"bool"},
-		{"name":"e","type":"bytes32[3][2]"}]`,
+		{"name":"e","type":"bytes32[3][2]"}], "type":"tuple"}]`,
 		unpacked: struct {
 			A int64
 			B *big.Int
@@ -855,21 +855,22 @@ var packUnpackTests = []packUnpackTest{
 			"0500000000000000000000000000000000000000000000000000000000000000", // struct[e] array[1][2]
 	},
 	{
-		def: `[{"name":"a","type":"string"}, 
+		def: `[{"components": [{"name":"a","type":"string"}, 
 		{"name":"b","type":"int64"}, 
 		{"name":"c","type":"bytes"}, 
 		{"name":"d","type":"string[]"},
 		{"name":"e","type":"int256[]"},
-		{"name":"f","type":"address[]"}]`,
+		{"name":"f","type":"address[]"}], "type":"tuple"}]`,
 		unpacked: struct {
-			FieldA string `abi:"a"` // Test whether abi tag works
-			FieldB int64  `abi:"b"`
-			C      []byte
-			D      []string
-			E      []*big.Int
-			F      []common.Address
+			A string
+			B int64
+			C []byte
+			D []string
+			E []*big.Int
+			F []common.Address
 		}{"foobar", 1, []byte{1}, []string{"foo", "bar"}, []*big.Int{big.NewInt(1), big.NewInt(-1)}, []common.Address{{1}, {2}}},
-		packed: "00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset
+		packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a
+			"00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset
 			"0000000000000000000000000000000000000000000000000000000000000001" + // struct[b]
 			"0000000000000000000000000000000000000000000000000000000000000100" + // struct[c] offset
 			"0000000000000000000000000000000000000000000000000000000000000140" + // struct[d] offset
@@ -894,23 +895,24 @@ var packUnpackTests = []packUnpackTest{
 			"0000000000000000000000000200000000000000000000000000000000000000", // common.Address{2}
 	},
 	{
-		def: `[{"components": [{"name": "a","type": "uint256"},	
+		def: `[{"components": [{ "type": "tuple","components": [{"name": "a","type": "uint256"},	
 							{"name": "b","type": "uint256[]"}],	
 							"name": "a","type": "tuple"},
-							{"name": "b","type": "uint256[]"}]`,
+							{"name": "b","type": "uint256[]"}],  "type": "tuple"}]`,
 		unpacked: struct {
 			A struct {
-				FieldA *big.Int `abi:"a"`
-				B      []*big.Int
+				A *big.Int
+				B []*big.Int
 			}
 			B []*big.Int
 		}{
 			A: struct {
-				FieldA *big.Int `abi:"a"` // Test whether abi tag works for nested tuple
-				B      []*big.Int
+				A *big.Int
+				B []*big.Int
 			}{big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2)}},
 			B: []*big.Int{big.NewInt(1), big.NewInt(2)}},
-		packed: "0000000000000000000000000000000000000000000000000000000000000040" + // a offset
+		packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a
+			"0000000000000000000000000000000000000000000000000000000000000040" + // a offset
 			"00000000000000000000000000000000000000000000000000000000000000e0" + // b offset
 			"0000000000000000000000000000000000000000000000000000000000000001" + // a.a value
 			"0000000000000000000000000000000000000000000000000000000000000040" + // a.b offset

+ 26 - 0
accounts/abi/reflect.go

@@ -24,6 +24,29 @@ import (
 	"strings"
 )
 
+// ConvertType converts an interface of a runtime type into a interface of the
+// given type
+// e.g. turn
+// var fields []reflect.StructField
+// fields = append(fields, reflect.StructField{
+// 		Name: "X",
+//		Type: reflect.TypeOf(new(big.Int)),
+//		Tag:  reflect.StructTag("json:\"" + "x" + "\""),
+// }
+// into
+// type TupleT struct { X *big.Int }
+func ConvertType(in interface{}, proto interface{}) interface{} {
+	protoType := reflect.TypeOf(proto)
+	if reflect.TypeOf(in).ConvertibleTo(protoType) {
+		return reflect.ValueOf(in).Convert(protoType).Interface()
+	}
+	// Use set as a last ditch effort
+	if err := set(reflect.ValueOf(proto), reflect.ValueOf(in)); err != nil {
+		panic(err)
+	}
+	return proto
+}
+
 // indirect recursively dereferences the value until it either gets the value
 // or finds a big.Int
 func indirect(v reflect.Value) reflect.Value {
@@ -119,6 +142,9 @@ func setSlice(dst, src reflect.Value) error {
 }
 
 func setArray(dst, src reflect.Value) error {
+	if src.Kind() == reflect.Ptr {
+		return set(dst, indirect(src))
+	}
 	array := reflect.New(dst.Type()).Elem()
 	min := src.Len()
 	if src.Len() > dst.Len() {

+ 70 - 0
accounts/abi/reflect_test.go

@@ -17,6 +17,7 @@
 package abi
 
 import (
+	"math/big"
 	"reflect"
 	"testing"
 )
@@ -189,3 +190,72 @@ func TestReflectNameToStruct(t *testing.T) {
 		})
 	}
 }
+
+func TestConvertType(t *testing.T) {
+	// Test Basic Struct
+	type T struct {
+		X *big.Int
+		Y *big.Int
+	}
+	// Create on-the-fly structure
+	var fields []reflect.StructField
+	fields = append(fields, reflect.StructField{
+		Name: "X",
+		Type: reflect.TypeOf(new(big.Int)),
+		Tag:  reflect.StructTag("json:\"" + "x" + "\""),
+	})
+	fields = append(fields, reflect.StructField{
+		Name: "Y",
+		Type: reflect.TypeOf(new(big.Int)),
+		Tag:  reflect.StructTag("json:\"" + "y" + "\""),
+	})
+	val := reflect.New(reflect.StructOf(fields))
+	val.Elem().Field(0).Set(reflect.ValueOf(big.NewInt(1)))
+	val.Elem().Field(1).Set(reflect.ValueOf(big.NewInt(2)))
+	// ConvertType
+	out := *ConvertType(val.Interface(), new(T)).(*T)
+	if out.X.Cmp(big.NewInt(1)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out.X, big.NewInt(1))
+	}
+	if out.Y.Cmp(big.NewInt(2)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out.Y, big.NewInt(2))
+	}
+	// Slice Type
+	val2 := reflect.MakeSlice(reflect.SliceOf(reflect.StructOf(fields)), 2, 2)
+	val2.Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1)))
+	val2.Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2)))
+	val2.Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3)))
+	val2.Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4)))
+	out2 := *ConvertType(val2.Interface(), new([]T)).(*[]T)
+	if out2[0].X.Cmp(big.NewInt(1)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1))
+	}
+	if out2[0].Y.Cmp(big.NewInt(2)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2))
+	}
+	if out2[1].X.Cmp(big.NewInt(3)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1))
+	}
+	if out2[1].Y.Cmp(big.NewInt(4)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2))
+	}
+	// Array Type
+	val3 := reflect.New(reflect.ArrayOf(2, reflect.StructOf(fields)))
+	val3.Elem().Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1)))
+	val3.Elem().Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2)))
+	val3.Elem().Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3)))
+	val3.Elem().Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4)))
+	out3 := *ConvertType(val3.Interface(), new([2]T)).(*[2]T)
+	if out3[0].X.Cmp(big.NewInt(1)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1))
+	}
+	if out3[0].Y.Cmp(big.NewInt(2)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2))
+	}
+	if out3[1].X.Cmp(big.NewInt(3)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1))
+	}
+	if out3[1].Y.Cmp(big.NewInt(4)) != 0 {
+		t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2))
+	}
+}

+ 29 - 31
accounts/abi/unpack_test.go

@@ -44,15 +44,13 @@ func TestUnpack(t *testing.T) {
 			if err != nil {
 				t.Fatalf("invalid hex %s: %v", test.packed, err)
 			}
-			outptr := reflect.New(reflect.TypeOf(test.unpacked))
-			err = abi.Unpack(outptr.Interface(), "method", encb)
+			out, err := abi.Unpack("method", encb)
 			if err != nil {
 				t.Errorf("test %d (%v) failed: %v", i, test.def, err)
 				return
 			}
-			out := outptr.Elem().Interface()
-			if !reflect.DeepEqual(test.unpacked, out) {
-				t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.unpacked, out)
+			if !reflect.DeepEqual(test.unpacked, ConvertType(out[0], test.unpacked)) {
+				t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.unpacked, out[0])
 			}
 		})
 	}
@@ -221,7 +219,7 @@ func TestLocalUnpackTests(t *testing.T) {
 				t.Fatalf("invalid hex %s: %v", test.enc, err)
 			}
 			outptr := reflect.New(reflect.TypeOf(test.want))
-			err = abi.Unpack(outptr.Interface(), "method", encb)
+			err = abi.UnpackIntoInterface(outptr.Interface(), "method", encb)
 			if err := test.checkError(err); err != nil {
 				t.Errorf("test %d (%v) failed: %v", i, test.def, err)
 				return
@@ -234,7 +232,7 @@ func TestLocalUnpackTests(t *testing.T) {
 	}
 }
 
-func TestUnpackSetDynamicArrayOutput(t *testing.T) {
+func TestUnpackIntoInterfaceSetDynamicArrayOutput(t *testing.T) {
 	abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`))
 	if err != nil {
 		t.Fatal(err)
@@ -249,7 +247,7 @@ func TestUnpackSetDynamicArrayOutput(t *testing.T) {
 	)
 
 	// test 32
-	err = abi.Unpack(&out32, "testDynamicFixedBytes32", marshalledReturn32)
+	err = abi.UnpackIntoInterface(&out32, "testDynamicFixedBytes32", marshalledReturn32)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -266,7 +264,7 @@ func TestUnpackSetDynamicArrayOutput(t *testing.T) {
 	}
 
 	// test 15
-	err = abi.Unpack(&out15, "testDynamicFixedBytes32", marshalledReturn15)
+	err = abi.UnpackIntoInterface(&out15, "testDynamicFixedBytes32", marshalledReturn15)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -367,7 +365,7 @@ func TestMethodMultiReturn(t *testing.T) {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
 			require := require.New(t)
-			err := abi.Unpack(tc.dest, "multi", data)
+			err := abi.UnpackIntoInterface(tc.dest, "multi", data)
 			if tc.error == "" {
 				require.Nil(err, "Should be able to unpack method outputs.")
 				require.Equal(tc.expected, tc.dest)
@@ -390,7 +388,7 @@ func TestMultiReturnWithArray(t *testing.T) {
 
 	ret1, ret1Exp := new([3]uint64), [3]uint64{9, 9, 9}
 	ret2, ret2Exp := new(uint64), uint64(8)
-	if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
+	if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
 		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(*ret1, ret1Exp) {
@@ -414,7 +412,7 @@ func TestMultiReturnWithStringArray(t *testing.T) {
 	ret2, ret2Exp := new(common.Address), common.HexToAddress("ab1257528b3782fb40d7ed5f72e624b744dffb2f")
 	ret3, ret3Exp := new([2]string), [2]string{"Ethereum", "Hello, Ethereum!"}
 	ret4, ret4Exp := new(bool), false
-	if err := abi.Unpack(&[]interface{}{ret1, ret2, ret3, ret4}, "multi", buff.Bytes()); err != nil {
+	if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2, ret3, ret4}, "multi", buff.Bytes()); err != nil {
 		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(*ret1, ret1Exp) {
@@ -452,7 +450,7 @@ func TestMultiReturnWithStringSlice(t *testing.T) {
 	buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000065")) // output[1][1] value
 	ret1, ret1Exp := new([]string), []string{"ethereum", "go-ethereum"}
 	ret2, ret2Exp := new([]*big.Int), []*big.Int{big.NewInt(100), big.NewInt(101)}
-	if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
+	if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
 		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(*ret1, ret1Exp) {
@@ -492,7 +490,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
 		{{0x411, 0x412, 0x413}, {0x421, 0x422, 0x423}},
 	}
 	ret2, ret2Exp := new(uint64), uint64(0x9876)
-	if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
+	if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
 		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(*ret1, ret1Exp) {
@@ -531,7 +529,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000a"))
 	buff.Write(common.Hex2Bytes("0102000000000000000000000000000000000000000000000000000000000000"))
 
-	err = abi.Unpack(&mixedBytes, "mixedBytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&mixedBytes, "mixedBytes", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	} else {
@@ -546,7 +544,7 @@ func TestUnmarshal(t *testing.T) {
 
 	// marshal int
 	var Int *big.Int
-	err = abi.Unpack(&Int, "int", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
+	err = abi.UnpackIntoInterface(&Int, "int", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
 	if err != nil {
 		t.Error(err)
 	}
@@ -557,7 +555,7 @@ func TestUnmarshal(t *testing.T) {
 
 	// marshal bool
 	var Bool bool
-	err = abi.Unpack(&Bool, "bool", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
+	err = abi.UnpackIntoInterface(&Bool, "bool", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
 	if err != nil {
 		t.Error(err)
 	}
@@ -574,7 +572,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(bytesOut)
 
 	var Bytes []byte
-	err = abi.Unpack(&Bytes, "bytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -590,7 +588,7 @@ func TestUnmarshal(t *testing.T) {
 	bytesOut = common.RightPadBytes([]byte("hello"), 64)
 	buff.Write(bytesOut)
 
-	err = abi.Unpack(&Bytes, "bytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -606,7 +604,7 @@ func TestUnmarshal(t *testing.T) {
 	bytesOut = common.RightPadBytes([]byte("hello"), 64)
 	buff.Write(bytesOut)
 
-	err = abi.Unpack(&Bytes, "bytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -616,7 +614,7 @@ func TestUnmarshal(t *testing.T) {
 	}
 
 	// marshal dynamic bytes output empty
-	err = abi.Unpack(&Bytes, "bytes", nil)
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", nil)
 	if err == nil {
 		t.Error("expected error")
 	}
@@ -627,7 +625,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000005"))
 	buff.Write(common.RightPadBytes([]byte("hello"), 32))
 
-	err = abi.Unpack(&Bytes, "bytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -641,7 +639,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(common.RightPadBytes([]byte("hello"), 32))
 
 	var hash common.Hash
-	err = abi.Unpack(&hash, "fixed", buff.Bytes())
+	err = abi.UnpackIntoInterface(&hash, "fixed", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -654,12 +652,12 @@ func TestUnmarshal(t *testing.T) {
 	// marshal error
 	buff.Reset()
 	buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020"))
-	err = abi.Unpack(&Bytes, "bytes", buff.Bytes())
+	err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
 	if err == nil {
 		t.Error("expected error")
 	}
 
-	err = abi.Unpack(&Bytes, "multi", make([]byte, 64))
+	err = abi.UnpackIntoInterface(&Bytes, "multi", make([]byte, 64))
 	if err == nil {
 		t.Error("expected error")
 	}
@@ -670,7 +668,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003"))
 	// marshal int array
 	var intArray [3]*big.Int
-	err = abi.Unpack(&intArray, "intArraySingle", buff.Bytes())
+	err = abi.UnpackIntoInterface(&intArray, "intArraySingle", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}
@@ -691,7 +689,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Write(common.Hex2Bytes("0000000000000000000000000100000000000000000000000000000000000000"))
 
 	var outAddr []common.Address
-	err = abi.Unpack(&outAddr, "addressSliceSingle", buff.Bytes())
+	err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes())
 	if err != nil {
 		t.Fatal("didn't expect error:", err)
 	}
@@ -718,7 +716,7 @@ func TestUnmarshal(t *testing.T) {
 		A []common.Address
 		B []common.Address
 	}
-	err = abi.Unpack(&outAddrStruct, "addressSliceDouble", buff.Bytes())
+	err = abi.UnpackIntoInterface(&outAddrStruct, "addressSliceDouble", buff.Bytes())
 	if err != nil {
 		t.Fatal("didn't expect error:", err)
 	}
@@ -746,7 +744,7 @@ func TestUnmarshal(t *testing.T) {
 	buff.Reset()
 	buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000100"))
 
-	err = abi.Unpack(&outAddr, "addressSliceSingle", buff.Bytes())
+	err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes())
 	if err == nil {
 		t.Fatal("expected error:", err)
 	}
@@ -769,7 +767,7 @@ func TestUnpackTuple(t *testing.T) {
 		B *big.Int
 	}{new(big.Int), new(big.Int)}
 
-	err = abi.Unpack(&v, "tuple", buff.Bytes())
+	err = abi.UnpackIntoInterface(&v, "tuple", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	} else {
@@ -841,7 +839,7 @@ func TestUnpackTuple(t *testing.T) {
 		A: big.NewInt(1),
 	}
 
-	err = abi.Unpack(&ret, "tuple", buff.Bytes())
+	err = abi.UnpackIntoInterface(&ret, "tuple", buff.Bytes())
 	if err != nil {
 		t.Error(err)
 	}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
contracts/checkpointoracle/contract/oracle.go


+ 1 - 1
contracts/checkpointoracle/contract/oracle.sol

@@ -1,4 +1,4 @@
-pragma solidity ^0.5.10;
+pragma solidity ^0.6.0;
 
 /**
  * @title CheckpointOracle

+ 1 - 1
go.mod

@@ -68,5 +68,5 @@ require (
 	gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
 	gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
 	gopkg.in/urfave/cli.v1 v1.20.0
-	gotest.tools v2.2.0+incompatible // indirect
+	gotest.tools v2.2.0+incompatible
 )

+ 5 - 13
mobile/bind.go

@@ -171,20 +171,12 @@ func (c *BoundContract) GetDeployer() *Transaction {
 // Call invokes the (constant) contract method with params as input values and
 // sets the output to result.
 func (c *BoundContract) Call(opts *CallOpts, out *Interfaces, method string, args *Interfaces) error {
-	if len(out.objects) == 1 {
-		result := out.objects[0]
-		if err := c.contract.Call(&opts.opts, result, method, args.objects...); err != nil {
-			return err
-		}
-		out.objects[0] = result
-	} else {
-		results := make([]interface{}, len(out.objects))
-		copy(results, out.objects)
-		if err := c.contract.Call(&opts.opts, &results, method, args.objects...); err != nil {
-			return err
-		}
-		copy(out.objects, results)
+	results := make([]interface{}, len(out.objects))
+	copy(results, out.objects)
+	if err := c.contract.Call(&opts.opts, &results, method, args.objects...); err != nil {
+		return err
 	}
+	copy(out.objects, results)
 	return nil
 }
 

+ 2 - 2
tests/fuzzers/abi/abifuzzer.go

@@ -30,7 +30,7 @@ import (
 
 func unpackPack(abi abi.ABI, method string, inputType []interface{}, input []byte) bool {
 	outptr := reflect.New(reflect.TypeOf(inputType))
-	if err := abi.Unpack(outptr.Interface(), method, input); err == nil {
+	if err := abi.UnpackIntoInterface(outptr.Interface(), method, input); err == nil {
 		output, err := abi.Pack(method, input)
 		if err != nil {
 			// We have some false positives as we can unpack these type successfully, but not pack them
@@ -51,7 +51,7 @@ func unpackPack(abi abi.ABI, method string, inputType []interface{}, input []byt
 func packUnpack(abi abi.ABI, method string, input []interface{}) bool {
 	if packed, err := abi.Pack(method, input); err == nil {
 		outptr := reflect.New(reflect.TypeOf(input))
-		err := abi.Unpack(outptr.Interface(), method, packed)
+		err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
 		if err != nil {
 			panic(err)
 		}

Vissa filer visades inte eftersom för många filer har ändrats