xrpl.js icon indicating copy to clipboard operation
xrpl.js copied to clipboard

Bug when transfer small number of token use scientific notation

Open code-brewer opened this issue 2 years ago • 6 comments

  const send_token_tx = {
    "TransactionType": "Payment",
    "Account": from.address,
    "Amount": {
      "currency": tk_name,
      "value": tk_amount,   // <==
      "issuer": tk_issuer
    },
    ...
  }

The value of 'Amount' can accept plain decimal "0.0000000000123456789123" and send Tx successfully.

But , if use scientific notation, such as (123456789123400e-26).toString() or (1.000005678901234e-10).toString(), alway raise error ValidationError: Serialized transaction does not match original txJSON. See error.data.

As comparison, send big number use 1.012345678901234e+19 is ok.

code-brewer avatar Aug 10 '22 02:08 code-brewer

I find the cause by another case that set trustline with a huge value (9e+51).toString().

In node_modules/xrpl/dist/npm/Wallet/index.js file, inside checkTxSerialization() function, the decoded.LimitAmount.value is '9000000000000000000000000000000000000000000000000000', while the txCopy.LimitAmount.value still is 9e+51.

thus won't pass the equal check.

I believe it is the same root for (123456789123400e-26).toString() or (1.000005678901234e-10).toString() value

image

code-brewer avatar Aug 10 '22 05:08 code-brewer

@code-brewer that is correct: we have a check in the serializer that ensures the serialized transaction is identical to the deserialized one, since any discrepancy could indicate a dangerous mismatch (i.e. you signed a transaction that isn't exactly what you expected).

Why do you want to provide numbers in scientific notation?

Is there a reason you can't use plain decimal (e.g. "0.0000000000123456789123")?

(Note: The cause of this error is the same as https://github.com/XRPLF/xrpl.js/issues/1553)

intelliot avatar Aug 12 '22 22:08 intelliot

Because the doc https://xrpl.org/currency-formats.html#string-numbers say we can use scientific notation, without state any limitation.

I try to use scientific notation because it is obvious to view power number. Then convert it to plain decimal by program.

Though (123456789123400e-26).toFixed(15).toString() can get decimal 0.000000000001235, while (1234567891234e+46).toFixed(15) not work.

I still struggle to find a way to solve it.

code-brewer avatar Aug 13 '22 13:08 code-brewer

If you look at the error data, you can see how the number is decoded by the deserializer. In the case of (1234567891234e+46), it decodes as:

'12345678912340000000000000000000000000000000000000000000000'

Thus, you can sign the transaction by specifying '12345678912340000000000000000000000000000000000000000000000' as the amount.

The reason we require this is that, due to rounding, we're not 100% confident that all possible numbers will encode in an expected manner. It's a safeguard to prevent people from assuming the rounding behavior of all possible numbers represented in scientific notation.

Does that help?

intelliot avatar Aug 14 '22 04:08 intelliot

Sorry for late response.

I'm using third party big number lib to convert exponent data to plain decimal now. It can accept any large or small number.

Again, I want to repeat, the doc https://xrpl.org/currency-formats.html#string-numbers say we can use scientific notation, without state any limitation, this maybe a pitfall! Because it actually only success when number is not too big.

code-brewer avatar Aug 20 '22 03:08 code-brewer

Thank you. Feel free to open a PR on xrpl-dev-portal to change that doc. However, I think the intent of the doc was to describe responses from rippled, not values that you specify when creating a transaction.

intelliot avatar Sep 15 '22 16:09 intelliot