diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index 91f9700d99dc0a8d8c055f848717d31911675bcc..01603b21796a7415f02440d88d3c8fd3f10becd9 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -63,9 +63,8 @@ func (abi ABI) pack(method Method, args ...interface{}) ([]byte, error) {
 			return nil, fmt.Errorf("`%s` %v", method.Name, err)
 		}
 
-		// check for a string or bytes input type
-		switch input.Type.T {
-		case StringTy, BytesTy:
+		// check for a slice type (string, bytes, slice)
+		if input.Type.T == StringTy || input.Type.T == BytesTy || input.Type.IsSlice {
 			// calculate the offset
 			offset := len(method.Inputs)*32 + len(variableInput)
 			// set the offset
@@ -73,7 +72,7 @@ func (abi ABI) pack(method Method, args ...interface{}) ([]byte, error) {
 			// Append the packed output to the variable input. The variable input
 			// will be appended at the end of the input.
 			variableInput = append(variableInput, packed...)
-		default:
+		} else {
 			// append the packed value to the input
 			ret = append(ret, packed...)
 		}
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index 66d2e1b39cf887e71404906f58dfe606a16847ea..db33face92b59c5dd894d4dfe6f53196d1c64a86 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -49,7 +49,9 @@ const jsondata2 = `
 	{ "type" : "function", "name" : "foo", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
 	{ "type" : "function", "name" : "bar", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
 	{ "type" : "function", "name" : "slice", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
-	{ "type" : "function", "name" : "slice256", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] }
+	{ "type" : "function", "name" : "slice256", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
+	{ "type" : "function", "name" : "sliceAddress", "const" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
+	{ "type" : "function", "name" : "sliceMultiAddress", "const" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
 ]`
 
 func TestType(t *testing.T) {
@@ -68,7 +70,7 @@ func TestType(t *testing.T) {
 	if typ.Kind != reflect.Slice {
 		t.Error("expected uint32[] to have type slice")
 	}
-	if typ.Type != ubig_ts {
+	if typ.Type != ubig_t {
 		t.Error("expcted uith32[] to have type uint64")
 	}
 
@@ -79,7 +81,7 @@ func TestType(t *testing.T) {
 	if typ.Kind != reflect.Slice {
 		t.Error("expected uint32[2] to have kind slice")
 	}
-	if typ.Type != ubig_ts {
+	if typ.Type != ubig_t {
 		t.Error("expcted uith32[2] to have type uint64")
 	}
 	if typ.Size != 2 {
@@ -202,16 +204,6 @@ func TestTestSlice(t *testing.T) {
 		t.FailNow()
 	}
 
-	addr := make([]byte, 20)
-	if _, err := abi.Pack("address", addr); err != nil {
-		t.Error(err)
-	}
-
-	addr = make([]byte, 21)
-	if _, err := abi.Pack("address", addr); err == nil {
-		t.Error("expected address of 21 width to throw")
-	}
-
 	slice := make([]byte, 2)
 	if _, err := abi.Pack("uint64[2]", slice); err != nil {
 		t.Error(err)
@@ -222,19 +214,6 @@ func TestTestSlice(t *testing.T) {
 	}
 }
 
-func TestTestAddress(t *testing.T) {
-	abi, err := JSON(strings.NewReader(jsondata2))
-	if err != nil {
-		t.Error(err)
-		t.FailNow()
-	}
-
-	addr := make([]byte, 20)
-	if _, err := abi.Pack("address", addr); err != nil {
-		t.Error(err)
-	}
-}
-
 func TestMethodSignature(t *testing.T) {
 	String, _ := NewType("string")
 	String32, _ := NewType("string32")
@@ -310,44 +289,69 @@ func TestPackSlice(t *testing.T) {
 	}
 
 	sig := crypto.Keccak256([]byte("slice(uint32[2])"))[:4]
-	sig = append(sig, make([]byte, 64)...)
-	sig[35] = 1
-	sig[67] = 2
+	sig = append(sig, common.LeftPadBytes([]byte{32}, 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("slice", []uint32{1, 2})
 	if err != nil {
 		t.Error(err)
-		t.FailNow()
 	}
 
 	if !bytes.Equal(packed, sig) {
 		t.Errorf("expected %x got %x", sig, packed)
 	}
-}
 
-func TestPackSliceBig(t *testing.T) {
-	abi, err := JSON(strings.NewReader(jsondata2))
+	var addrA, addrB = common.Address{1}, common.Address{2}
+	sig = abi.Methods["sliceAddress"].Id()
+	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.Error(err)
-		t.FailNow()
+		t.Fatal(err)
+	}
+	if !bytes.Equal(packed, sig) {
+		t.Errorf("expected %x got %x", sig, packed)
 	}
 
-	sig := crypto.Keccak256([]byte("slice256(uint256[2])"))[:4]
-	sig = append(sig, make([]byte, 64)...)
-	sig[35] = 1
-	sig[67] = 2
+	var addrC, addrD = common.Address{3}, common.Address{4}
+	sig = abi.Methods["sliceMultiAddress"].Id()
+	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)
+	}
 
-	packed, err := abi.Pack("slice256", []*big.Int{big.NewInt(1), big.NewInt(2)})
+	sig = crypto.Keccak256([]byte("slice256(uint256[2])"))[:4]
+	sig = append(sig, common.LeftPadBytes([]byte{32}, 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("slice256", []*big.Int{big.NewInt(1), big.NewInt(2)})
 	if err != nil {
 		t.Error(err)
-		t.FailNow()
 	}
 
 	if !bytes.Equal(packed, sig) {
 		t.Errorf("expected %x got %x", sig, packed)
 	}
 }
-
 func ExampleJSON() {
 	const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
 
@@ -370,7 +374,7 @@ func TestInputVariableInputLength(t *testing.T) {
 	{ "type" : "function", "name" : "strOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
 	{ "type" : "function", "name" : "bytesOne", "const" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
 	{ "type" : "function", "name" : "strTwo", "const" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
-]`
+	]`
 
 	abi, err := JSON(strings.NewReader(definition))
 	if err != nil {
@@ -493,35 +497,6 @@ func TestInputVariableInputLength(t *testing.T) {
 	}
 }
 
-func TestBytes(t *testing.T) {
-	const definition = `[
-	{ "type" : "function", "name" : "balance", "const" : true, "inputs" : [ { "name" : "address", "type" : "bytes20" } ] },
-	{ "type" : "function", "name" : "send", "const" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
-]`
-
-	abi, err := JSON(strings.NewReader(definition))
-	if err != nil {
-		t.Fatal(err)
-	}
-	ok := make([]byte, 20)
-	_, err = abi.Pack("balance", ok)
-	if err != nil {
-		t.Error(err)
-	}
-
-	toosmall := make([]byte, 19)
-	_, err = abi.Pack("balance", toosmall)
-	if err != nil {
-		t.Error(err)
-	}
-
-	toobig := make([]byte, 21)
-	_, err = abi.Pack("balance", toobig)
-	if err == nil {
-		t.Error("expected error")
-	}
-}
-
 func TestDefaultFunctionParsing(t *testing.T) {
 	const definition = `[{ "name" : "balance" }]`
 
diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go
index 02609d567a45a3a93daedc8480f3af30f958d9d4..084701de5bd2dde90fd4c65b2845be627b35350e 100644
--- a/accounts/abi/numbers.go
+++ b/accounts/abi/numbers.go
@@ -117,8 +117,6 @@ func packNum(value reflect.Value, to byte) []byte {
 // checks whether the given reflect value is signed. This also works for slices with a number type
 func isSigned(v reflect.Value) bool {
 	switch v.Type() {
-	case ubig_ts, big_ts, big_t, ubig_t:
-		return true
 	case int_ts, int8_ts, int16_ts, int32_ts, int64_ts, int_t, int8_t, int16_t, int32_t, int64_t:
 		return true
 	}
diff --git a/accounts/abi/numbers_test.go b/accounts/abi/numbers_test.go
index 78dc57543b1ec2c99e61844528daeeb068aedce0..6590e41a6febe0c3fb8de5a808848a3970f42076 100644
--- a/accounts/abi/numbers_test.go
+++ b/accounts/abi/numbers_test.go
@@ -81,8 +81,4 @@ func TestSigned(t *testing.T) {
 	if !isSigned(reflect.ValueOf(int(10))) {
 		t.Error()
 	}
-
-	if !isSigned(reflect.ValueOf(big.NewInt(10))) {
-		t.Error()
-	}
 }
diff --git a/accounts/abi/type.go b/accounts/abi/type.go
index c08b744f7c6a2d886f205d9a181459379843d999..18cd04672c25788e15ef93572b64e93061031597 100644
--- a/accounts/abi/type.go
+++ b/accounts/abi/type.go
@@ -96,63 +96,57 @@ func NewType(t string) (typ Type, err error) {
 		t += "256"
 	}
 
-	if isslice {
+	switch vtype {
+	case "int":
+		typ.Kind = reflect.Ptr
+		typ.Type = big_t
+		typ.Size = 256
+		typ.T = IntTy
+	case "uint":
+		typ.Kind = reflect.Ptr
+		typ.Type = ubig_t
+		typ.Size = 256
+		typ.T = UintTy
+	case "bool":
+		typ.Kind = reflect.Bool
+		typ.T = BoolTy
+	case "real": // TODO
+		typ.Kind = reflect.Invalid
+	case "address":
 		typ.Kind = reflect.Slice
-		typ.Size = size
-		switch vtype {
-		case "int":
-			typ.Type = big_ts
-		case "uint":
-			typ.Type = ubig_ts
-		default:
-			return Type{}, fmt.Errorf("unsupported arg slice type: %s", t)
-		}
-	} else {
-		switch vtype {
-		case "int":
-			typ.Kind = reflect.Ptr
-			typ.Type = big_t
-			typ.Size = 256
-			typ.T = IntTy
-		case "uint":
-			typ.Kind = reflect.Ptr
-			typ.Type = ubig_t
-			typ.Size = 256
-			typ.T = UintTy
-		case "bool":
-			typ.Kind = reflect.Bool
-			typ.T = BoolTy
-		case "real": // TODO
-			typ.Kind = reflect.Invalid
-		case "address":
-			typ.Kind = reflect.Slice
-			typ.Type = address_t
-			typ.Size = 20
-			typ.T = AddressTy
-		case "string":
-			typ.Kind = reflect.String
-			typ.Size = -1
-			typ.T = StringTy
-			if vsize > 0 {
-				typ.Size = 32
-			}
-		case "hash":
-			typ.Kind = reflect.Slice
+		typ.Type = address_t
+		typ.Size = 20
+		typ.T = AddressTy
+	case "string":
+		typ.Kind = reflect.String
+		typ.Size = -1
+		typ.T = StringTy
+		if vsize > 0 {
 			typ.Size = 32
-			typ.Type = hash_t
-			typ.T = HashTy
-		case "bytes":
-			typ.Kind = reflect.Slice
-			typ.Type = byte_ts
-			typ.Size = vsize
-			if vsize == 0 {
-				typ.T = BytesTy
-			} else {
-				typ.T = FixedBytesTy
-			}
-		default:
-			return Type{}, fmt.Errorf("unsupported arg type: %s", t)
 		}
+	case "hash":
+		typ.Kind = reflect.Slice
+		typ.Size = 32
+		typ.Type = hash_t
+		typ.T = HashTy
+	case "bytes":
+		typ.Kind = reflect.Slice
+		typ.Type = byte_ts
+		typ.Size = vsize
+		if vsize == 0 {
+			typ.T = BytesTy
+		} else {
+			typ.T = FixedBytesTy
+		}
+	default:
+		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
+	}
+
+	// if the type is a slice we must set Kind to a reflect.Slice
+	// so that serialisation can be determined based on this kind.
+	if isslice {
+		typ.Kind = reflect.Slice
+		typ.Size = size
 	}
 	typ.stringKind = t
 
@@ -203,7 +197,7 @@ func (t Type) pack(v interface{}) ([]byte, error) {
 
 		return packBytesSlice([]byte(value.String()), value.Len()), nil
 	case reflect.Slice:
-		// if the param is a bytes type, pack the slice up as a string
+		// Byte slice is a special case, it gets treated as a single value
 		if t.T == BytesTy {
 			return packBytesSlice(value.Bytes(), value.Len()), nil
 		}
@@ -212,21 +206,20 @@ func (t Type) pack(v interface{}) ([]byte, error) {
 			return nil, fmt.Errorf("%v out of bound. %d for %d", value.Kind(), value.Len(), t.Size)
 		}
 
-		// Address is a special slice. The slice acts as one rather than a list of elements.
-		if t.T == AddressTy {
-			return common.LeftPadBytes(v.([]byte), 32), nil
-		}
-
 		// Signed / Unsigned check
-		if (t.T != IntTy && isSigned(value)) || (t.T == UintTy && isSigned(value)) {
+		if value.Type() == big_t && (t.T != IntTy && isSigned(value)) || (t.T == UintTy && isSigned(value)) {
 			return nil, fmt.Errorf("slice of incompatible types.")
 		}
 
 		var packed []byte
 		for i := 0; i < value.Len(); i++ {
-			packed = append(packed, packNum(value.Index(i), t.T)...)
+			val, err := t.pack(value.Index(i).Interface())
+			if err != nil {
+				return nil, err
+			}
+			packed = append(packed, val...)
 		}
-		return packed, nil
+		return packBytesSlice(packed, value.Len()), nil
 	case reflect.Bool:
 		if value.Bool() {
 			return common.LeftPadBytes(common.Big1.Bytes(), 32), nil