diff --git a/accounts/abi/error_handling.go b/accounts/abi/error_handling.go index c106e9ac43..0000c181ad 100644 --- a/accounts/abi/error_handling.go +++ b/accounts/abi/error_handling.go @@ -26,11 +26,19 @@ var ( errBadBool = errors.New("abi: improperly encoded boolean value") errBadUint8 = errors.New("abi: improperly encoded uint8 value") errBadUint16 = errors.New("abi: improperly encoded uint16 value") + errBadUint24 = errors.New("abi: improperly encoded uint24 value") errBadUint32 = errors.New("abi: improperly encoded uint32 value") + errBadUint40 = errors.New("abi: improperly encoded uint40 value") + errBadUint48 = errors.New("abi: improperly encoded uint48 value") + errBadUint56 = errors.New("abi: improperly encoded uint56 value") errBadUint64 = errors.New("abi: improperly encoded uint64 value") errBadInt8 = errors.New("abi: improperly encoded int8 value") errBadInt16 = errors.New("abi: improperly encoded int16 value") + errBadInt24 = errors.New("abi: improperly encoded int24 value") errBadInt32 = errors.New("abi: improperly encoded int32 value") + errBadInt40 = errors.New("abi: improperly encoded int40 value") + errBadInt48 = errors.New("abi: improperly encoded int48 value") + errBadInt56 = errors.New("abi: improperly encoded int56 value") errBadInt64 = errors.New("abi: improperly encoded int64 value") ) diff --git a/accounts/abi/packing_test.go b/accounts/abi/packing_test.go index eae3b0df20..9912bac036 100644 --- a/accounts/abi/packing_test.go +++ b/accounts/abi/packing_test.go @@ -72,6 +72,19 @@ var packUnpackTests = []packUnpackTest{ packed: "0000000000000000000000000000000000000000000000000000000000000001", unpacked: big.NewInt(1), }, + { + def: `[{"type": "uint24"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + unpacked: uint32(1), + }, + { + def: `[{"type": "uint24[]"}]`, + unpacked: []uint32{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, { def: `[{"type": "uint32"}]`, packed: "0000000000000000000000000000000000000000000000000000000000000001", @@ -85,6 +98,45 @@ var packUnpackTests = []packUnpackTest{ "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002", }, + { + def: `[{"type": "uint40"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + unpacked: uint64(1), + }, + { + def: `[{"type": "uint40[]"}]`, + unpacked: []uint64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "uint48"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + unpacked: uint64(1), + }, + { + def: `[{"type": "uint48[]"}]`, + unpacked: []uint64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "uint56"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + unpacked: uint64(1), + }, + { + def: `[{"type": "uint56[]"}]`, + unpacked: []uint64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, { def: `[{"type": "uint64"}]`, unpacked: uint64(2), @@ -137,6 +189,19 @@ var packUnpackTests = []packUnpackTest{ "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002", }, + { + def: `[{"type": "int24"}]`, + unpacked: int32(2), + packed: "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int24[]"}]`, + unpacked: []int32{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, { def: `[{"type": "int17"}]`, packed: "0000000000000000000000000000000000000000000000000000000000000001", @@ -160,6 +225,45 @@ var packUnpackTests = []packUnpackTest{ "0000000000000000000000000000000000000000000000000000000000000001" + "0000000000000000000000000000000000000000000000000000000000000002", }, + { + def: `[{"type": "int40"}]`, + unpacked: int64(2), + packed: "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int40[]"}]`, + unpacked: []int64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int48"}]`, + unpacked: int64(2), + packed: "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int48[]"}]`, + unpacked: []int64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int56"}]`, + unpacked: int64(2), + packed: "0000000000000000000000000000000000000000000000000000000000000002", + }, + { + def: `[{"type": "int56[]"}]`, + unpacked: []int64{1, 2}, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, { def: `[{"type": "int64"}]`, unpacked: int64(2), diff --git a/accounts/abi/reflect.go b/accounts/abi/reflect.go index 729ca93c54..e6487aad6a 100644 --- a/accounts/abi/reflect.go +++ b/accounts/abi/reflect.go @@ -68,9 +68,9 @@ func reflectIntType(unsigned bool, size int) reflect.Type { return reflect.TypeOf(uint8(0)) case 16: return reflect.TypeOf(uint16(0)) - case 32: + case 24, 32: return reflect.TypeOf(uint32(0)) - case 64: + case 40, 48, 56, 64: return reflect.TypeOf(uint64(0)) } } @@ -79,9 +79,9 @@ func reflectIntType(unsigned bool, size int) reflect.Type { return reflect.TypeOf(int8(0)) case 16: return reflect.TypeOf(int16(0)) - case 32: + case 24, 32: return reflect.TypeOf(int32(0)) - case 64: + case 40, 48, 56, 64: return reflect.TypeOf(int64(0)) } return reflect.TypeOf(&big.Int{}) diff --git a/accounts/abi/type_test.go b/accounts/abi/type_test.go index 95922548c4..7cea6f245d 100644 --- a/accounts/abi/type_test.go +++ b/accounts/abi/type_test.go @@ -140,12 +140,13 @@ func TestTypeCheck(t *testing.T) { {"uint64", nil, uint64(1), ""}, {"int8", nil, int8(1), ""}, {"int16", nil, int16(1), ""}, + {"int24", nil, int32(1), ""}, {"int32", nil, int32(1), ""}, {"int64", nil, int64(1), ""}, - {"uint24", nil, big.NewInt(1), ""}, - {"uint40", nil, big.NewInt(1), ""}, - {"uint48", nil, big.NewInt(1), ""}, - {"uint56", nil, big.NewInt(1), ""}, + {"uint24", nil, uint32(1), ""}, + {"uint40", nil, uint64(1), ""}, + {"uint48", nil, uint64(1), ""}, + {"uint56", nil, uint64(1), ""}, {"uint72", nil, big.NewInt(1), ""}, {"uint80", nil, big.NewInt(1), ""}, {"uint88", nil, big.NewInt(1), ""}, @@ -169,10 +170,10 @@ func TestTypeCheck(t *testing.T) { {"uint232", nil, big.NewInt(1), ""}, {"uint240", nil, big.NewInt(1), ""}, {"uint248", nil, big.NewInt(1), ""}, - {"int24", nil, big.NewInt(1), ""}, - {"int40", nil, big.NewInt(1), ""}, - {"int48", nil, big.NewInt(1), ""}, - {"int56", nil, big.NewInt(1), ""}, + {"int24", nil, int32(1), ""}, + {"int40", nil, int64(1), ""}, + {"int48", nil, int64(1), ""}, + {"int56", nil, int64(1), ""}, {"int72", nil, big.NewInt(1), ""}, {"int80", nil, big.NewInt(1), ""}, {"int88", nil, big.NewInt(1), ""}, @@ -213,6 +214,28 @@ func TestTypeCheck(t *testing.T) { {"uint16[3]", nil, [4]uint16{1, 2, 3}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"}, {"uint16[3]", nil, []uint16{1, 2, 3}, ""}, {"uint16[3]", nil, []uint16{1, 2, 3, 4}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"}, + {"uint24[]", nil, []uint32{1, 2, 3}, ""}, + {"uint24[]", nil, [3]uint32{1, 2, 3}, ""}, + {"uint24[]", nil, []uint64{1, 2, 3}, "abi: cannot use []uint64 as type [0]uint32 as argument"}, + {"uint24[3]", nil, [3]uint64{1, 2, 3}, "abi: cannot use [3]uint64 as type [3]uint32 as argument"}, + {"uint24[3]", nil, [4]uint32{1, 2, 3}, "abi: cannot use [4]uint32 as type [3]uint32 as argument"}, + {"uint24[3]", nil, []uint32{1, 2, 3}, ""}, + {"uint24[3]", nil, []uint32{1, 2, 3, 4}, "abi: cannot use [4]uint32 as type [3]uint32 as argument"}, + {"uint40[]", nil, []uint64{1, 2, 3}, ""}, + {"uint40[]", nil, [3]uint64{1, 2, 3}, ""}, + {"uint40[3]", nil, [4]uint64{1, 2, 3}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, + {"uint40[3]", nil, []uint64{1, 2, 3}, ""}, + {"uint40[3]", nil, []uint64{1, 2, 3, 4}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, + {"uint48[]", nil, []uint64{1, 2, 3}, ""}, + {"uint48[]", nil, [3]uint64{1, 2, 3}, ""}, + {"uint48[3]", nil, [4]uint64{1, 2, 3}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, + {"uint48[3]", nil, []uint64{1, 2, 3}, ""}, + {"uint48[3]", nil, []uint64{1, 2, 3, 4}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, + {"uint56[]", nil, []uint64{1, 2, 3}, ""}, + {"uint56[]", nil, [3]uint64{1, 2, 3}, ""}, + {"uint56[3]", nil, [4]uint64{1, 2, 3}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, + {"uint56[3]", nil, []uint64{1, 2, 3}, ""}, + {"uint56[3]", nil, []uint64{1, 2, 3, 4}, "abi: cannot use [4]uint64 as type [3]uint64 as argument"}, {"address[]", nil, []common.Address{{1}}, ""}, {"address[1]", nil, []common.Address{{1}}, ""}, {"address[1]", nil, [1]common.Address{{1}}, ""}, diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index 905b5ce629..18b667aaa2 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -51,11 +51,31 @@ func ReadInteger(typ Type, b []byte) (interface{}, error) { return nil, errBadUint16 } return uint16(u64), nil + case 24: + if !isu64 || u64 > 1<<24-1 { + return nil, errBadUint24 + } + return uint32(u64), nil case 32: if !isu64 || u64 > math.MaxUint32 { return nil, errBadUint32 } return uint32(u64), nil + case 40: + if !isu64 || u64 > 1<<40-1 { + return nil, errBadUint40 + } + return u64, nil + case 48: + if !isu64 || u64 > 1<<48-1 { + return nil, errBadUint48 + } + return u64, nil + case 56: + if !isu64 || u64 > 1<<56-1 { + return nil, errBadUint56 + } + return u64, nil case 64: if !isu64 { return nil, errBadUint64 @@ -87,19 +107,38 @@ func ReadInteger(typ Type, b []byte) (interface{}, error) { return nil, errBadInt16 } return int16(i64), nil + case 24: + if !isi64 || i64 < -1<<23 || i64 > 1<<23-1 { + return nil, errBadInt24 + } + return int32(i64), nil case 32: if !isi64 || i64 < math.MinInt32 || i64 > math.MaxInt32 { return nil, errBadInt32 } return int32(i64), nil + case 40: + if !isi64 || i64 < -1<<39 || i64 > 1<<39-1 { + return nil, errBadInt40 + } + return i64, nil + case 48: + if !isi64 || i64 < -1<<47 || i64 > 1<<47-1 { + return nil, errBadInt48 + } + return i64, nil + case 56: + if !isi64 || i64 < -1<<55 || i64 > 1<<55-1 { + return nil, errBadInt56 + } + return i64, nil case 64: if !isi64 { return nil, errBadInt64 } return i64, nil default: - // the only case left for integer is int256 - + // The only remaining case for an integer is a range where int64 > x <= int256 return ret, nil } } diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index 7df7b9c403..48682b7936 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -999,6 +999,17 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) { err: nil, expectValue: uint16(math.MaxUint16), }, + { + decodeType: "uint24", + inputValue: big.NewInt(1 << 24), + err: errBadUint24, + }, + { + decodeType: "uint24", + inputValue: big.NewInt(1<<24 - 1), + err: nil, + expectValue: uint32(1<<24 - 1), + }, { decodeType: "uint32", inputValue: big.NewInt(math.MaxUint32 + 1), @@ -1010,6 +1021,39 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) { err: nil, expectValue: uint32(math.MaxUint32), }, + { + decodeType: "uint40", + inputValue: big.NewInt(1 << 40), + err: errBadUint40, + }, + { + decodeType: "uint40", + inputValue: big.NewInt(1<<40 - 1), + err: nil, + expectValue: uint64(1<<40 - 1), + }, + { + decodeType: "uint48", + inputValue: big.NewInt(1 << 48), + err: errBadUint48, + }, + { + decodeType: "uint48", + inputValue: big.NewInt(1<<48 - 1), + err: nil, + expectValue: uint64(1<<48 - 1), + }, + { + decodeType: "uint56", + inputValue: big.NewInt(1 << 56), + err: errBadUint56, + }, + { + decodeType: "uint56", + inputValue: big.NewInt(1<<56 - 1), + err: nil, + expectValue: uint64(1<<56 - 1), + }, { decodeType: "uint64", inputValue: maxU64Plus1, @@ -1059,6 +1103,28 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) { err: nil, expectValue: int16(math.MaxInt16), }, + { + decodeType: "int24", + inputValue: big.NewInt(-1<<23 - 1), + err: errBadInt24, + }, + { + decodeType: "int24", + inputValue: big.NewInt(1<<23 - 1 + 1), + err: errBadInt24, + }, + { + decodeType: "int24", + inputValue: big.NewInt(-1 << 23), + err: nil, + expectValue: int32(-1 << 23), + }, + { + decodeType: "int24", + inputValue: big.NewInt(1<<23 - 1), + err: nil, + expectValue: int32(1<<23 - 1), + }, { decodeType: "int32", inputValue: big.NewInt(math.MaxInt32 + 1), @@ -1075,6 +1141,72 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) { err: nil, expectValue: int32(math.MaxInt32), }, + { + decodeType: "int40", + inputValue: big.NewInt(-1<<39 - 1), + err: errBadInt40, + }, + { + decodeType: "int40", + inputValue: big.NewInt(1<<39 - 1 + 1), + err: errBadInt40, + }, + { + decodeType: "int40", + inputValue: big.NewInt(-1 << 39), + err: nil, + expectValue: int64(-1 << 39), + }, + { + decodeType: "int40", + inputValue: big.NewInt(1<<39 - 1), + err: nil, + expectValue: int64(1<<39 - 1), + }, + { + decodeType: "int48", + inputValue: big.NewInt(-1<<47 - 1), + err: errBadInt48, + }, + { + decodeType: "int48", + inputValue: big.NewInt(1<<47 - 1 + 1), + err: errBadInt48, + }, + { + decodeType: "int48", + inputValue: big.NewInt(-1 << 47), + err: nil, + expectValue: int64(-1 << 47), + }, + { + decodeType: "int48", + inputValue: big.NewInt(1<<47 - 1), + err: nil, + expectValue: int64(1<<47 - 1), + }, + { + decodeType: "int56", + inputValue: big.NewInt(-1<<55 - 1), + err: errBadInt56, + }, + { + decodeType: "int56", + inputValue: big.NewInt(1<<55 - 1 + 1), + err: errBadInt56, + }, + { + decodeType: "int56", + inputValue: big.NewInt(-1 << 55), + err: nil, + expectValue: int64(-1 << 55), + }, + { + decodeType: "int56", + inputValue: big.NewInt(1<<55 - 1), + err: nil, + expectValue: int64(1<<55 - 1), + }, { decodeType: "int64", inputValue: new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)),