XRPL-Labs / xrpld-hooks

ISC License
94 stars 28 forks source link

Incorrect `float_sto` behavior upon receiving XFL canonical zero as an input (Version: latest) #69

Open 9oelM opened 1 year ago

9oelM commented 1 year ago

Issue Description

It seems that float_sto does not correctly serialize canonical zero in XFL into zero in XRPL token amount.

Steps to Reproduce

Go to hooks builder, deploy and trigger this hook

#include "hookapi.h"

#define XFL_BYTE_LEN 8
// canonical zero in XFL is just 0
#define XFL_ZERO 0 

int64_t hook(uint32_t reserved ) {
    int64_t state_data[1];
    if (float_sto(state_data, XFL_BYTE_LEN, 0, 0, 0, 0, XFL_ZERO, (uint32_t)(-1)) != XFL_BYTE_LEN) {
        rollback(SBUF("failed serialize into amount"), -1);                                                  
    }
    TRACEHEX(state_data);
    if (state_set(SBUF(state_data), "test", 32) != XFL_BYTE_LEN) {                       
      rollback(SBUF("failed to set new state"), -1);                 
    }                                                                          

    accept (0,0,0); 

    _g(1,1);   // every hook needs to import guard function and use it at least once
    // unreachable
    return 0;
}

You can view all related files on https://gist.github.com/9oelM/ea72f4d7cfae2bd90c09cc6fc09924db#file-starter-c. but i only modified the .c file anyway.

Expected Result

float_sto should correctly serialize canonical zero in XFL into zero in XRPL amount format, which is 0x8000000000000000 or 0b1000000000000000000000000000000000000000000000000000000000000000.

image

Actual Result

float_sto serializes canonical zero in XFL as 0xC000000000000000 or 0b1100000000000000000000000000000000000000000000000000000000000000.

This is not a valid number as an XRPL amount, because the most significant bit is 1 to indicate that the amount is not XRP. But the second most significant bit is also 1. This bit is originally meant to indicate that the number is positive. But this does not apply to zero in XRPL token amount. Zero is always 0x8000000000000000.

float_sto in the example code above is not supposed to output an XRP amount too, because the field code parameter in float_sto is -1, and "if this field is 0 no field code is prepended to the output, and no issuer or currency code is appended, but serialization proceeds as though the amount is an XRP native amount rather than a floating point.".

So we can presumably suspect that this might be a bug in float_sto.

Environment

I do not know which version is hosted at the public node right now, but I'm just using that.

Supporting Files

image

Txn containing the state change: https://hooks-testnet-v3-explorer.xrpl-labs.com/tx/4CC64667005E1DCE31BF4F8845077F73D353F27181C3FCD80E66CC7D1B55CA26

image