diff options
author | Diep Pham <mrfavadi@gmail.com> | 2018-09-04 23:53:28 +0800 |
---|---|---|
committer | Felix Lange <fjl@users.noreply.github.com> | 2018-09-04 23:53:28 +0800 |
commit | 42bd67bd6fd599a5583452f011152a0c26c9dff4 (patch) | |
tree | 41176161eda207d0fd4b27358d5d3adb00d4f252 /accounts/abi | |
parent | beee7a52e08f6e948d4cca9de8ff59d5b8305917 (diff) | |
download | dexon-42bd67bd6fd599a5583452f011152a0c26c9dff4.tar.gz dexon-42bd67bd6fd599a5583452f011152a0c26c9dff4.tar.zst dexon-42bd67bd6fd599a5583452f011152a0c26c9dff4.zip |
accounts/abi: fix unpacking of negative int256 (#17583)
Diffstat (limited to 'accounts/abi')
-rw-r--r-- | accounts/abi/unpack.go | 28 | ||||
-rw-r--r-- | accounts/abi/unpack_test.go | 5 |
2 files changed, 30 insertions, 3 deletions
diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index 793d515ad..d5875140c 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -25,8 +25,17 @@ import ( "github.com/ethereum/go-ethereum/common" ) +var ( + maxUint256 = big.NewInt(0).Add( + big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil), + big.NewInt(-1)) + maxInt256 = big.NewInt(0).Add( + big.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil), + big.NewInt(-1)) +) + // reads the integer based on its kind -func readInteger(kind reflect.Kind, b []byte) interface{} { +func readInteger(typ byte, kind reflect.Kind, b []byte) interface{} { switch kind { case reflect.Uint8: return b[len(b)-1] @@ -45,7 +54,20 @@ func readInteger(kind reflect.Kind, b []byte) interface{} { case reflect.Int64: return int64(binary.BigEndian.Uint64(b[len(b)-8:])) default: - return new(big.Int).SetBytes(b) + // the only case lefts for integer is int256/uint256. + // big.SetBytes can't tell if a number is negative, positive on itself. + // On EVM, if the returned number > max int256, it is negative. + ret := new(big.Int).SetBytes(b) + if typ == UintTy { + return ret + } + + if ret.Cmp(maxInt256) > 0 { + ret.Add(maxUint256, big.NewInt(0).Neg(ret)) + ret.Add(ret, big.NewInt(1)) + ret.Neg(ret) + } + return ret } } @@ -179,7 +201,7 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) { case StringTy: // variable arrays are written at the end of the return bytes return string(output[begin : begin+end]), nil case IntTy, UintTy: - return readInteger(t.Kind, returnOutput), nil + return readInteger(t.T, t.Kind, returnOutput), nil case BoolTy: return readBool(returnOutput) case AddressTy: diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index bdbab10b4..97552b90c 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -118,6 +118,11 @@ var unpackTests = []unpackTest{ want: big.NewInt(1), }, { + def: `[{"type": "int256"}]`, + enc: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + want: big.NewInt(-1), + }, + { def: `[{"type": "address"}]`, enc: "0000000000000000000000000100000000000000000000000000000000000000", want: common.Address{1}, |