From 0f9539e1e3e77bb181d67591cfbb77f6a17e5537 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= <peterke@gmail.com>
Date: Fri, 10 Jun 2016 10:35:10 +0300
Subject: [PATCH] accounts/abi: fix uint64 upper range encoding.

---
 accounts/abi/numbers.go      | 12 +++--------
 accounts/abi/numbers_test.go | 42 +++++++++++++++++++++++++-----------
 2 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go
index 06c4422f9..3d5842292 100644
--- a/accounts/abi/numbers.go
+++ b/accounts/abi/numbers.go
@@ -56,27 +56,21 @@ var (
 	big_ts   = reflect.TypeOf([]*big.Int(nil))
 )
 
-// U256 will ensure unsigned 256bit on big nums
+// U256 converts a big Int into a 256bit EVM number.
 func U256(n *big.Int) []byte {
 	return common.LeftPadBytes(common.U256(n).Bytes(), 32)
 }
 
-// S256 will ensure signed 256bit on big nums
-func U2U256(n uint64) []byte {
-	return U256(big.NewInt(int64(n)))
-}
-
 // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
 func packNum(value reflect.Value) []byte {
 	switch kind := value.Kind(); kind {
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		return U2U256(value.Uint())
+		return U256(new(big.Int).SetUint64(value.Uint()))
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return U2U256(uint64(value.Int()))
+		return U256(big.NewInt(value.Int()))
 	case reflect.Ptr:
 		return U256(value.Interface().(*big.Int))
 	}
-
 	return nil
 }
 
diff --git a/accounts/abi/numbers_test.go b/accounts/abi/numbers_test.go
index f409aa60f..44afe8647 100644
--- a/accounts/abi/numbers_test.go
+++ b/accounts/abi/numbers_test.go
@@ -18,6 +18,7 @@ package abi
 
 import (
 	"bytes"
+	"math"
 	"math/big"
 	"reflect"
 	"testing"
@@ -34,21 +35,38 @@ func TestNumberTypes(t *testing.T) {
 }
 
 func TestPackNumber(t *testing.T) {
-	ubytes := make([]byte, 32)
-	ubytes[31] = 1
-	maxunsigned := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
+	tests := []struct {
+		value  reflect.Value
+		packed []byte
+	}{
+		// Protocol limits
+		{reflect.ValueOf(0), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+		{reflect.ValueOf(1), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
+		{reflect.ValueOf(-1), []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}},
+
+		// Type corner cases
+		{reflect.ValueOf(uint8(math.MaxUint8)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}},
+		{reflect.ValueOf(uint16(math.MaxUint16)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255}},
+		{reflect.ValueOf(uint32(math.MaxUint32)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255}},
+		{reflect.ValueOf(uint64(math.MaxUint64)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
 
-	packed := packNum(reflect.ValueOf(1))
-	if !bytes.Equal(packed, ubytes) {
-		t.Errorf("expected %x got %x", ubytes, packed)
+		{reflect.ValueOf(int8(math.MaxInt8)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}},
+		{reflect.ValueOf(int16(math.MaxInt16)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255}},
+		{reflect.ValueOf(int32(math.MaxInt32)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255}},
+		{reflect.ValueOf(int64(math.MaxInt64)), []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, 255, 255, 255}},
+
+		{reflect.ValueOf(int8(math.MinInt8)), []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128}},
+		{reflect.ValueOf(int16(math.MinInt16)), []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0}},
+		{reflect.ValueOf(int32(math.MinInt32)), []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0}},
+		{reflect.ValueOf(int64(math.MinInt64)), []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0}},
 	}
-	packed = packNum(reflect.ValueOf(-1))
-	if !bytes.Equal(packed, maxunsigned) {
-		t.Errorf("expected %x got %x", maxunsigned, packed)
+	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)
+		}
 	}
-
-	packed = packNum(reflect.ValueOf("string"))
-	if packed != nil {
+	if packed := packNum(reflect.ValueOf("string")); packed != nil {
 		t.Errorf("expected 'string' to pack to nil. got %x instead", packed)
 	}
 }
-- 
GitLab