5

I have a contract with a function that takes as parameter a bytes32, and a mapping that uses a bytes32 as key.

In geth, it seems like I can call contract.foo("0x123abc") and contract.foo(0x123abc), but I'm not sure they give the same results.

Same for contract.mymap("0x123abc") and contract.mymap(0x123abc), are they the same ? Are they always processed as 0x123abc0000000000000000000000000000000000000000000000000000000000 ? Bytes are similar to strings but I'm not sure of the difference.


I can't test anything I want on my contract, but I checked and both map(0x1234567890abcdef123) and map("0x1234567890abcdef123") work but give different results. Which one should I use ?

2 Answers 2

6

Always use quotes. JavaScript has a maximum integer precision of 64 bits. This means that if your number is over 8 bytes, and you type it in without quotes, you will immediately lose precision.

For example:

0x1122334455667700 - 1
> 0x1122334455667700

0x1122334455667700 - 0x1122334455667701
> 0

The correct way:

web3.toBigNumber("0x1122334455667700").minus(1).toString(16)
>'11223344556676ff'

bytes and bytes32 are actually very different. bytes is identical to string, whereas bytes32 is identical to uint256.

If your function is expecting a bytes, web3 will interpret your string as ASCII, i.e. "12345" will be interpreted as "\x30\x31\x32\x33\x34". If it's expecting a numeric type (i.e. bytes32), it will interpret the string as a BigNumber. If you want to be sure and reduce ambiguity, you can manually convert your numerics to BigNumbers using web3.toBigNumber().

For example, if you're having issues with '0x123abc' try

web3.toBigNumber('0x123abc') 

instead

5
  • '0x123abc' with quotes is causing different behavior for the OP. So I suggest decimal quoted '1194684'. Is there something better?
    – eth
    Jan 12, 2017 at 20:50
  • edited to show example Jan 12, 2017 at 20:54
  • Good idea, already upvoted your answer but will include your suggestion.
    – eth
    Jan 12, 2017 at 21:21
  • Thanks, that's a really good explanation. The loss of precision explains why I get different results ! I oversimplified, actually the mapping give the same value for 0x123abc and "0x123abc" but it's different with longer numbers, like 0x584832ca31d3f972b95d2f53. I didn't think of that so I simplified my example, but now it's edited to be more accurate. Jan 13, 2017 at 9:59
  • I don't do any mathematical operations on them, but now it's clear it's precision loss when I do : web3.toHex(0x584832ca31d3f972b95d2f5300000000) and I get "0x584832ca31d3f6f94f4ed2610a400000". On the other hand, web3.toHex() with quotes works like expected. Jan 13, 2017 at 10:04
3

From the ABI:

  • bytes is right-padded with zeroes (to a length of 32). "0x123abc" with quotes is bytes.

  • types like bytes32, uint, int are left-padded with zeroes (to a length of 32). 0x123abc without quotes is a number (in base 16).

Since the contract takes bytes32, use 0x123abc without quotes or its decimal equivalent 1194684 to reduce confusion with hex. (To be safe, use quotes for '1194684' so that it's interpreted as a BigNumber.)

EDIT: Per @Tjaden To use '0x123abc', use web3.toBigNumber('0x123abc').

5
  • Thanks ! I didn't know bytes32 was equivalent to BigNumber. What is hex then ? I have long hex values I store I'm the blockchain, it seemed easier to use bytes as they're written as hex. Jan 12, 2017 at 19:28
  • You should essentially always use quotes. When you don't use quotes, the number is immediately converted to a JS number, which has a maximum precision of 64 bits. When you use quotes, web3 interprets it as a bigNumber, which is almost always preferable Jan 12, 2017 at 20:18
  • @TeleportingGoat bytes32 is just a 256-bit number and number-wise hex is base 16. Data stored in the blockchain is binary, which is more compactly viewable as hex: that hex could be interpreted as a number, a string, or just as a raw blob of data. I'll update answer to emphasize that '1194684' should be in quotes.
    – eth
    Jan 12, 2017 at 20:24
  • "use 0x123abc without quotes" this will lead to a loss of precision as well. JS will just immediately convert it to a 64-bit type Jan 12, 2017 at 20:27
  • @TjadenHess Good point but '0x123abc' with quotes is causing different behavior for the OP. So I suggest decimal quoted '1194684'. Is there something better?
    – eth
    Jan 12, 2017 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.