diff --git a/accounts/abi/error.go b/accounts/abi/error.go
index 9ee27010aa7d6f3e4b6bb5799df389d6e8bfaeaa..8d61d574c5f48c90d59c5831511ce7d2afb77cb7 100644
--- a/accounts/abi/error.go
+++ b/accounts/abi/error.go
@@ -39,11 +39,11 @@ func formatSliceString(kind reflect.Kind, sliceSize int) string {
 // type in t.
 func sliceTypeCheck(t Type, val reflect.Value) error {
 	if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
-		return typeErr(formatSliceString(t.Type.Kind(), t.Size), val.Type())
+		return typeErr(formatSliceString(t.getType().Kind(), t.Size), val.Type())
 	}
 
 	if t.T == ArrayTy && val.Len() != t.Size {
-		return typeErr(formatSliceString(t.Elem.Type.Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
+		return typeErr(formatSliceString(t.Elem.getType().Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len()))
 	}
 
 	if t.Elem.T == SliceTy || t.Elem.T == ArrayTy {
@@ -52,8 +52,8 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
 		}
 	}
 
-	if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Type.Kind() {
-		return typeErr(formatSliceString(t.Elem.Type.Kind(), t.Size), val.Type())
+	if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.getType().Kind() {
+		return typeErr(formatSliceString(t.Elem.getType().Kind(), t.Size), val.Type())
 	}
 	return nil
 }
@@ -66,10 +66,10 @@ func typeCheck(t Type, value reflect.Value) error {
 	}
 
 	// Check base type validity. Element types will be checked later on.
-	if t.Type.Kind() != value.Kind() {
-		return typeErr(t.Type.Kind(), value.Kind())
+	if t.getType().Kind() != value.Kind() {
+		return typeErr(t.getType().Kind(), value.Kind())
 	} else if t.T == FixedBytesTy && t.Size != value.Len() {
-		return typeErr(t.Type, value.Type())
+		return typeErr(t.getType(), value.Type())
 	} else {
 		return nil
 	}
diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go
deleted file mode 100644
index 03cbc708528c121f624bfdbd167fdff64329b6f2..0000000000000000000000000000000000000000
--- a/accounts/abi/numbers.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// 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 (
-	"math/big"
-	"reflect"
-
-	"github.com/ethereum/go-ethereum/common"
-)
-
-var (
-	bigT      = reflect.TypeOf(&big.Int{})
-	derefbigT = reflect.TypeOf(big.Int{})
-	uint8T    = reflect.TypeOf(uint8(0))
-	uint16T   = reflect.TypeOf(uint16(0))
-	uint32T   = reflect.TypeOf(uint32(0))
-	uint64T   = reflect.TypeOf(uint64(0))
-	int8T     = reflect.TypeOf(int8(0))
-	int16T    = reflect.TypeOf(int16(0))
-	int32T    = reflect.TypeOf(int32(0))
-	int64T    = reflect.TypeOf(int64(0))
-	addressT  = reflect.TypeOf(common.Address{})
-)
diff --git a/accounts/abi/reflect.go b/accounts/abi/reflect.go
index b0b7327c06a147edb8ffa65c8633a7d37dc6fbe1..4bb6c4fa09b72a1d45fd25f4a304fc5fa75085b8 100644
--- a/accounts/abi/reflect.go
+++ b/accounts/abi/reflect.go
@@ -18,6 +18,7 @@ package abi
 
 import (
 	"fmt"
+	"math/big"
 	"reflect"
 	"strings"
 )
@@ -25,7 +26,7 @@ import (
 // indirect recursively dereferences the value until it either gets the value
 // or finds a big.Int
 func indirect(v reflect.Value) reflect.Value {
-	if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT {
+	if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) {
 		return indirect(v.Elem())
 	}
 	return v
@@ -45,26 +46,26 @@ func reflectIntType(unsigned bool, size int) reflect.Type {
 	if unsigned {
 		switch size {
 		case 8:
-			return uint8T
+			return reflect.TypeOf(uint8(0))
 		case 16:
-			return uint16T
+			return reflect.TypeOf(uint16(0))
 		case 32:
-			return uint32T
+			return reflect.TypeOf(uint32(0))
 		case 64:
-			return uint64T
+			return reflect.TypeOf(uint64(0))
 		}
 	}
 	switch size {
 	case 8:
-		return int8T
+		return reflect.TypeOf(int8(0))
 	case 16:
-		return int16T
+		return reflect.TypeOf(int16(0))
 	case 32:
-		return int32T
+		return reflect.TypeOf(int32(0))
 	case 64:
-		return int64T
+		return reflect.TypeOf(int64(0))
 	}
-	return bigT
+	return reflect.TypeOf(&big.Int{})
 }
 
 // mustArrayToBytesSlice creates a new byte slice with the exact same size as value
@@ -84,7 +85,7 @@ func set(dst, src reflect.Value) error {
 	switch {
 	case dstType.Kind() == reflect.Interface && dst.Elem().IsValid():
 		return set(dst.Elem(), src)
-	case dstType.Kind() == reflect.Ptr && dstType.Elem() != derefbigT:
+	case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}):
 		return set(dst.Elem(), src)
 	case srcType.AssignableTo(dstType) && dst.CanSet():
 		dst.Set(src)
diff --git a/accounts/abi/type.go b/accounts/abi/type.go
index 6975dab14dd067e43e4e48b70c1bd68cb4bda295..09d75fb8872922f92ecdce39d45586ebdb88fa65 100644
--- a/accounts/abi/type.go
+++ b/accounts/abi/type.go
@@ -23,6 +23,8 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+
+	"github.com/ethereum/go-ethereum/common"
 )
 
 // Type enumerator
@@ -45,16 +47,16 @@ const (
 // Type is the reflection of the supported argument type
 type Type struct {
 	Elem *Type
-	Type reflect.Type
 	Size int
 	T    byte // Our own type checking
 
 	stringKind string // holds the unparsed string for deriving signatures
 
 	// Tuple relative fields
-	TupleRawName  string   // Raw struct name defined in source code, may be empty.
-	TupleElems    []*Type  // Type information of all tuple fields
-	TupleRawNames []string // Raw field name of all tuple fields
+	TupleRawName  string       // Raw struct name defined in source code, may be empty.
+	TupleElems    []*Type      // Type information of all tuple fields
+	TupleRawNames []string     // Raw field name of all tuple fields
+	TupleType     reflect.Type // Underlying struct of the tuple
 }
 
 var (
@@ -94,7 +96,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 			// is a slice
 			typ.T = SliceTy
 			typ.Elem = &embeddedType
-			typ.Type = reflect.SliceOf(embeddedType.Type)
 			typ.stringKind = embeddedType.stringKind + sliced
 		} else if len(intz) == 1 {
 			// is a array
@@ -104,7 +105,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 			if err != nil {
 				return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
 			}
-			typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type)
 			typ.stringKind = embeddedType.stringKind + sliced
 		} else {
 			return Type{}, fmt.Errorf("invalid formatting of array type")
@@ -136,31 +136,24 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 	// varType is the parsed abi type
 	switch varType := parsedType[1]; varType {
 	case "int":
-		typ.Type = reflectIntType(false, varSize)
 		typ.Size = varSize
 		typ.T = IntTy
 	case "uint":
-		typ.Type = reflectIntType(true, varSize)
 		typ.Size = varSize
 		typ.T = UintTy
 	case "bool":
 		typ.T = BoolTy
-		typ.Type = reflect.TypeOf(bool(false))
 	case "address":
-		typ.Type = addressT
 		typ.Size = 20
 		typ.T = AddressTy
 	case "string":
-		typ.Type = reflect.TypeOf("")
 		typ.T = StringTy
 	case "bytes":
 		if varSize == 0 {
 			typ.T = BytesTy
-			typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0)))
 		} else {
 			typ.T = FixedBytesTy
 			typ.Size = varSize
-			typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0)))
 		}
 	case "tuple":
 		var (
@@ -180,7 +173,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 			}
 			fields = append(fields, reflect.StructField{
 				Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field.
-				Type: cType.Type,
+				Type: cType.getType(),
 				Tag:  reflect.StructTag("json:\"" + c.Name + "\""),
 			})
 			elems = append(elems, &cType)
@@ -191,7 +184,8 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 			}
 		}
 		expression += ")"
-		typ.Type = reflect.StructOf(fields)
+
+		typ.TupleType = reflect.StructOf(fields)
 		typ.TupleElems = elems
 		typ.TupleRawNames = names
 		typ.T = TupleTy
@@ -210,7 +204,6 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 	case "function":
 		typ.T = FunctionTy
 		typ.Size = 24
-		typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
 	default:
 		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
 	}
@@ -218,6 +211,41 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
 	return
 }
 
+func (t Type) getType() reflect.Type {
+	switch t.T {
+	case IntTy:
+		return reflectIntType(false, t.Size)
+	case UintTy:
+		return reflectIntType(true, t.Size)
+	case BoolTy:
+		return reflect.TypeOf(false)
+	case StringTy:
+		return reflect.TypeOf("")
+	case SliceTy:
+		return reflect.SliceOf(t.Elem.getType())
+	case ArrayTy:
+		return reflect.ArrayOf(t.Size, t.Elem.getType())
+	case TupleTy:
+		return t.TupleType
+	case AddressTy:
+		return reflect.TypeOf(common.Address{})
+	case FixedBytesTy:
+		return reflect.ArrayOf(t.Size, reflect.TypeOf(byte(0)))
+	case BytesTy:
+		return reflect.SliceOf(reflect.TypeOf(byte(0)))
+	case HashTy:
+		// hashtype currently not used
+		return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
+	case FixedPointTy:
+		// fixedpoint type currently not used
+		return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
+	case FunctionTy:
+		return reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
+	default:
+		panic("Invalid type")
+	}
+}
+
 // String implements Stringer
 func (t Type) String() (out string) {
 	return t.stringKind
diff --git a/accounts/abi/type_test.go b/accounts/abi/type_test.go
index 1c8a9fefe5f393320c2795fe0917cfac6619a0c1..566f991c54182d4a82a7b9809c548862a14fbdc2 100644
--- a/accounts/abi/type_test.go
+++ b/accounts/abi/type_test.go
@@ -36,58 +36,58 @@ func TestTypeRegexp(t *testing.T) {
 		components []ArgumentMarshaling
 		kind       Type
 	}{
-		{"bool", nil, Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}},
-		{"bool[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]bool(nil)), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}},
-		{"bool[2]", nil, Type{Size: 2, T: ArrayTy, Type: reflect.TypeOf([2]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}},
-		{"bool[2][]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][2]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}},
-		{"bool[][]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}},
-		{"bool[][2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}},
-		{"bool[2][2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}},
-		{"bool[2][][2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][][2]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([][2]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}, stringKind: "bool[2][][2]"}},
-		{"bool[2][2][2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2][2]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][2]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}, stringKind: "bool[2][2][2]"}},
-		{"bool[][][]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][][]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([][]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}, stringKind: "bool[][][]"}},
-		{"bool[][2][]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][2][]bool{}), Elem: &Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]bool{}), Elem: &Type{T: SliceTy, Type: reflect.TypeOf([]bool{}), Elem: &Type{T: BoolTy, Type: reflect.TypeOf(bool(false)), stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}, stringKind: "bool[][2][]"}},
-		{"int8", nil, Type{Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}},
-		{"int16", nil, Type{Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}},
-		{"int32", nil, Type{Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}},
-		{"int64", nil, Type{Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}},
-		{"int256", nil, Type{Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}},
-		{"int8[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]int8{}), Elem: &Type{Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[]"}},
-		{"int8[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int8{}), Elem: &Type{Type: int8T, Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[2]"}},
-		{"int16[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]int16{}), Elem: &Type{Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[]"}},
-		{"int16[2]", nil, Type{Size: 2, T: ArrayTy, Type: reflect.TypeOf([2]int16{}), Elem: &Type{Type: int16T, Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[2]"}},
-		{"int32[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]int32{}), Elem: &Type{Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
-		{"int32[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int32{}), Elem: &Type{Type: int32T, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
-		{"int64[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]int64{}), Elem: &Type{Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[]"}},
-		{"int64[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]int64{}), Elem: &Type{Type: int64T, Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[2]"}},
-		{"int256[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
-		{"int256[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]*big.Int{}), Elem: &Type{Type: bigT, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
-		{"uint8", nil, Type{Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}},
-		{"uint16", nil, Type{Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}},
-		{"uint32", nil, Type{Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}},
-		{"uint64", nil, Type{Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}},
-		{"uint256", nil, Type{Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}},
-		{"uint8[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]uint8{}), Elem: &Type{Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[]"}},
-		{"uint8[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint8{}), Elem: &Type{Type: uint8T, Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[2]"}},
-		{"uint16[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]uint16{}), Elem: &Type{Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[]"}},
-		{"uint16[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint16{}), Elem: &Type{Type: uint16T, Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[2]"}},
-		{"uint32[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]uint32{}), Elem: &Type{Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
-		{"uint32[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint32{}), Elem: &Type{Type: uint32T, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
-		{"uint64[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]uint64{}), Elem: &Type{Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[]"}},
-		{"uint64[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]uint64{}), Elem: &Type{Type: uint64T, Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[2]"}},
-		{"uint256[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]*big.Int{}), Elem: &Type{Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
-		{"uint256[2]", nil, Type{T: ArrayTy, Type: reflect.TypeOf([2]*big.Int{}), Size: 2, Elem: &Type{Type: bigT, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
-		{"bytes32", nil, Type{T: FixedBytesTy, Size: 32, Type: reflect.TypeOf([32]byte{}), stringKind: "bytes32"}},
-		{"bytes[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][]byte{}), Elem: &Type{Type: reflect.TypeOf([]byte{}), T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}},
-		{"bytes[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][]byte{}), Elem: &Type{T: BytesTy, Type: reflect.TypeOf([]byte{}), stringKind: "bytes"}, stringKind: "bytes[2]"}},
-		{"bytes32[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([][32]byte{}), Elem: &Type{Type: reflect.TypeOf([32]byte{}), T: FixedBytesTy, Size: 32, stringKind: "bytes32"}, stringKind: "bytes32[]"}},
-		{"bytes32[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2][32]byte{}), Elem: &Type{T: FixedBytesTy, Size: 32, Type: reflect.TypeOf([32]byte{}), stringKind: "bytes32"}, stringKind: "bytes32[2]"}},
-		{"string", nil, Type{T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}},
-		{"string[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]string{}), Elem: &Type{Type: reflect.TypeOf(""), T: StringTy, stringKind: "string"}, stringKind: "string[]"}},
-		{"string[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]string{}), Elem: &Type{T: StringTy, Type: reflect.TypeOf(""), stringKind: "string"}, stringKind: "string[2]"}},
-		{"address", nil, Type{Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}},
-		{"address[]", nil, Type{T: SliceTy, Type: reflect.TypeOf([]common.Address{}), Elem: &Type{Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
-		{"address[2]", nil, Type{T: ArrayTy, Size: 2, Type: reflect.TypeOf([2]common.Address{}), Elem: &Type{Type: addressT, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
+		{"bool", nil, Type{T: BoolTy, stringKind: "bool"}},
+		{"bool[]", nil, Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}},
+		{"bool[2]", nil, Type{Size: 2, T: ArrayTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}},
+		{"bool[2][]", nil, Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}},
+		{"bool[][]", nil, Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}},
+		{"bool[][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}},
+		{"bool[2][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}},
+		{"bool[2][][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}, stringKind: "bool[2][][2]"}},
+		{"bool[2][2][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}, stringKind: "bool[2][2][2]"}},
+		{"bool[][][]", nil, Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}, stringKind: "bool[][][]"}},
+		{"bool[][2][]", nil, Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}, stringKind: "bool[][2][]"}},
+		{"int8", nil, Type{Size: 8, T: IntTy, stringKind: "int8"}},
+		{"int16", nil, Type{Size: 16, T: IntTy, stringKind: "int16"}},
+		{"int32", nil, Type{Size: 32, T: IntTy, stringKind: "int32"}},
+		{"int64", nil, Type{Size: 64, T: IntTy, stringKind: "int64"}},
+		{"int256", nil, Type{Size: 256, T: IntTy, stringKind: "int256"}},
+		{"int8[]", nil, Type{T: SliceTy, Elem: &Type{Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[]"}},
+		{"int8[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[2]"}},
+		{"int16[]", nil, Type{T: SliceTy, Elem: &Type{Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[]"}},
+		{"int16[2]", nil, Type{Size: 2, T: ArrayTy, Elem: &Type{Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[2]"}},
+		{"int32[]", nil, Type{T: SliceTy, Elem: &Type{Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
+		{"int32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
+		{"int64[]", nil, Type{T: SliceTy, Elem: &Type{Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[]"}},
+		{"int64[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[2]"}},
+		{"int256[]", nil, Type{T: SliceTy, Elem: &Type{Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
+		{"int256[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
+		{"uint8", nil, Type{Size: 8, T: UintTy, stringKind: "uint8"}},
+		{"uint16", nil, Type{Size: 16, T: UintTy, stringKind: "uint16"}},
+		{"uint32", nil, Type{Size: 32, T: UintTy, stringKind: "uint32"}},
+		{"uint64", nil, Type{Size: 64, T: UintTy, stringKind: "uint64"}},
+		{"uint256", nil, Type{Size: 256, T: UintTy, stringKind: "uint256"}},
+		{"uint8[]", nil, Type{T: SliceTy, Elem: &Type{Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[]"}},
+		{"uint8[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[2]"}},
+		{"uint16[]", nil, Type{T: SliceTy, Elem: &Type{Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[]"}},
+		{"uint16[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[2]"}},
+		{"uint32[]", nil, Type{T: SliceTy, Elem: &Type{Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
+		{"uint32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
+		{"uint64[]", nil, Type{T: SliceTy, Elem: &Type{Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[]"}},
+		{"uint64[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[2]"}},
+		{"uint256[]", nil, Type{T: SliceTy, Elem: &Type{Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
+		{"uint256[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
+		{"bytes32", nil, Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}},
+		{"bytes[]", nil, Type{T: SliceTy, Elem: &Type{T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}},
+		{"bytes[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[2]"}},
+		{"bytes32[]", nil, Type{T: SliceTy, Elem: &Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}, stringKind: "bytes32[]"}},
+		{"bytes32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}, stringKind: "bytes32[2]"}},
+		{"string", nil, Type{T: StringTy, stringKind: "string"}},
+		{"string[]", nil, Type{T: SliceTy, Elem: &Type{T: StringTy, stringKind: "string"}, stringKind: "string[]"}},
+		{"string[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: StringTy, stringKind: "string"}, stringKind: "string[2]"}},
+		{"address", nil, Type{Size: 20, T: AddressTy, stringKind: "address"}},
+		{"address[]", nil, Type{T: SliceTy, Elem: &Type{Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
+		{"address[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
 		// TODO when fixed types are implemented properly
 		// {"fixed", nil, Type{}},
 		// {"fixed128x128", nil, Type{}},
@@ -95,14 +95,14 @@ func TestTypeRegexp(t *testing.T) {
 		// {"fixed[2]", nil, Type{}},
 		// {"fixed128x128[]", nil, Type{}},
 		// {"fixed128x128[2]", nil, Type{}},
-		{"tuple", []ArgumentMarshaling{{Name: "a", Type: "int64"}}, Type{T: TupleTy, Type: reflect.TypeOf(struct {
+		{"tuple", []ArgumentMarshaling{{Name: "a", Type: "int64"}}, Type{T: TupleTy, TupleType: reflect.TypeOf(struct {
 			A int64 `json:"a"`
 		}{}), stringKind: "(int64)",
-			TupleElems: []*Type{{T: IntTy, Type: reflect.TypeOf(int64(0)), Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"a"}}},
-		{"tuple with long name", []ArgumentMarshaling{{Name: "aTypicalParamName", Type: "int64"}}, Type{T: TupleTy, Type: reflect.TypeOf(struct {
+			TupleElems: []*Type{{T: IntTy, Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"a"}}},
+		{"tuple with long name", []ArgumentMarshaling{{Name: "aTypicalParamName", Type: "int64"}}, Type{T: TupleTy, TupleType: reflect.TypeOf(struct {
 			ATypicalParamName int64 `json:"aTypicalParamName"`
 		}{}), stringKind: "(int64)",
-			TupleElems: []*Type{{T: IntTy, Type: reflect.TypeOf(int64(0)), Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"aTypicalParamName"}}},
+			TupleElems: []*Type{{T: IntTy, Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"aTypicalParamName"}}},
 	}
 
 	for _, tt := range tests {
@@ -312,12 +312,12 @@ func TestInternalType(t *testing.T) {
 	internalType := "struct a.b[]"
 	kind := Type{
 		T: TupleTy,
-		Type: reflect.TypeOf(struct {
+		TupleType: reflect.TypeOf(struct {
 			A int64 `json:"a"`
 		}{}),
 		stringKind:    "(int64)",
 		TupleRawName:  "ab[]",
-		TupleElems:    []*Type{{T: IntTy, Type: reflect.TypeOf(int64(0)), Size: 64, stringKind: "int64"}},
+		TupleElems:    []*Type{{T: IntTy, Size: 64, stringKind: "int64"}},
 		TupleRawNames: []string{"a"},
 	}
 
diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go
index dede1a5f7dbfffb5fbeab1ed2960f85744050d81..6c8fce0cbc96da8a9c805aa50f7e131f8f0aaeca 100644
--- a/accounts/abi/unpack.go
+++ b/accounts/abi/unpack.go
@@ -34,32 +34,36 @@ var (
 
 // ReadInteger reads the integer based on its kind and returns the appropriate value
 func ReadInteger(typ Type, b []byte) interface{} {
-	switch typ.Type {
-	case uint8T:
-		return b[len(b)-1]
-	case uint16T:
-		return binary.BigEndian.Uint16(b[len(b)-2:])
-	case uint32T:
-		return binary.BigEndian.Uint32(b[len(b)-4:])
-	case uint64T:
-		return binary.BigEndian.Uint64(b[len(b)-8:])
-	case int8T:
+	if typ.T == UintTy {
+		switch typ.Size {
+		case 8:
+			return b[len(b)-1]
+		case 16:
+			return binary.BigEndian.Uint16(b[len(b)-2:])
+		case 32:
+			return binary.BigEndian.Uint32(b[len(b)-4:])
+		case 64:
+			return binary.BigEndian.Uint64(b[len(b)-8:])
+		default:
+			// the only case left for unsigned integer is uint256.
+			return new(big.Int).SetBytes(b)
+		}
+	}
+	switch typ.Size {
+	case 8:
 		return int8(b[len(b)-1])
-	case int16T:
+	case 16:
 		return int16(binary.BigEndian.Uint16(b[len(b)-2:]))
-	case int32T:
+	case 32:
 		return int32(binary.BigEndian.Uint32(b[len(b)-4:]))
-	case int64T:
+	case 64:
 		return int64(binary.BigEndian.Uint64(b[len(b)-8:]))
 	default:
-		// the only case left for integer is int256/uint256.
-		ret := new(big.Int).SetBytes(b)
-		if typ.T == UintTy {
-			return ret
-		}
+		// the only case left for integer is int256
 		// big.SetBytes can't tell if a number is negative or positive in itself.
 		// On EVM, if the returned number > max int256, it is negative.
 		// A number is > max int256 if the bit at position 255 is set.
+		ret := new(big.Int).SetBytes(b)
 		if ret.Bit(255) == 1 {
 			ret.Add(MaxUint256, new(big.Int).Neg(ret))
 			ret.Add(ret, common.Big1)
@@ -106,7 +110,7 @@ func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
 		return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array")
 	}
 	// convert
-	array := reflect.New(t.Type).Elem()
+	array := reflect.New(t.getType()).Elem()
 
 	reflect.Copy(array, reflect.ValueOf(word[0:t.Size]))
 	return array.Interface(), nil
@@ -127,10 +131,10 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
 
 	if t.T == SliceTy {
 		// declare our slice
-		refSlice = reflect.MakeSlice(t.Type, size, size)
+		refSlice = reflect.MakeSlice(t.getType(), size, size)
 	} else if t.T == ArrayTy {
 		// declare our array
-		refSlice = reflect.New(t.Type).Elem()
+		refSlice = reflect.New(t.getType()).Elem()
 	} else {
 		return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
 	}
@@ -154,7 +158,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
 }
 
 func forTupleUnpack(t Type, output []byte) (interface{}, error) {
-	retval := reflect.New(t.Type).Elem()
+	retval := reflect.New(t.getType()).Elem()
 	virtualArgs := 0
 	for index, elem := range t.TupleElems {
 		marshalledValue, err := ToGoType((index+virtualArgs)*32, *elem, output)
diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go
index 97a2723080447604dfacbadfa91097ed41bc92df..7a590b4b4b3861425a9cb4bd120c3f2cc0c33d66 100644
--- a/accounts/abi/unpack_test.go
+++ b/accounts/abi/unpack_test.go
@@ -33,7 +33,7 @@ import (
 // TestUnpack tests the general pack/unpack tests in packing_test.go
 func TestUnpack(t *testing.T) {
 	for i, test := range packUnpackTests {
-		t.Run(strconv.Itoa(i), func(t *testing.T) {
+		t.Run(strconv.Itoa(i)+" "+test.def, func(t *testing.T) {
 			//Unpack
 			def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def)
 			abi, err := JSON(strings.NewReader(def))