Description
I would like to report some behaviour that seems unexpected to me.
What is the current behavior?
Encoding a negative BigInt
value will return the hex of its absolute value. So -42
will be encoded as 0x2a
.
What is the expected behavior?
Looking into the code, it looks like num::BigInt::to_bytes_be
returns the big-endian bytes for its absolute value. This causes typeConversions.bigIntToHex
to encode absolute values of its BigInt
parameter.
This is a bit unexpected to me, and I would have expected either:
- To sign prefix the hex value (so
42
becomes0x2a
and-42
becomes-0x2a
). This is more inline with hownum::BigInt
would hex-format values. - To hex encode the value in 2's compliment notation. (so
42
becomes0x2a
and-42
becomes0xd6
). In looking at the code, this encoding implementation requires no leading 0s in the hex representation. This would mean that with 2's compliment, there would be multiple numbers with the same hex representation (for example255
would be0xff
and-1
would also be0xff
). - Disallow hex-encoding negative big integers. From the documentation for the
typeConversions.bigIntToHex
implementation in theHostExports
, it mentionsgo-ethereum
encoding rules as the reference. By those rules, hex marshalling for negative numbers is explicitly prohibited, so following that here would also make sense:Negative integers are not supported at this time. Attempting to marshal them will return an error. Values larger than 256bits are rejected by Unmarshal but will be marshaled without error.
Unfortunately, all of these suggestions would be breaking changes (which I imagine should be avoided for subgraph host function implementations).