Appearance
Float and Amount APIs
This page documents the sixteen float-and-amount Hook APIs: the float_* family that lets a hook do arbitrary-precision decimal arithmetic on token amounts and serialize the result into (or read it out of) the ledger's Amount format.
All signatures are copied verbatim from hook/extern.h. Return codes reference the shared error table in ../../glossary.md; values come from include/xrpl/hook/Enum.h and hook/error.h, and every behaviour below is taken from the implementations in src/xrpld/app/hook/detail/applyHook.cpp and src/xrpld/app/hook/detail/HookAPI.cpp.
What an XFL is
An XFL (the hooks floating-point format) is a single int64_t that encodes a decimal number the same way the ledger encodes IOU (token) amounts: a sign, a normalized mantissa, and a base-10 exponent. Its valid ranges are fixed (src/xrpld/app/hook/HookAPI.h):
- Mantissa — exactly 16 significant digits:
1000000000000000(minMantissa) to9999999999999999(maxMantissa). Non-zero values are always normalized to this width. - Exponent —
-96(minExponent) to80(maxExponent). - Zero — represented by the literal
int64_tvalue0(the one XFL with no mantissa).
A value's XFL bit-pattern is a positive int64_t; the number's own sign lives inside that encoding, not in the sign of the int64_t. As a result any negative int64_t is not a valid XFL — passing one (for example -1) returns INVALID_FLOAT. This is why the "invalid float" sentinel has the unusual value INVALID_FLOAT = -10024 (deliberately not -24): it is a number chosen so it can never itself be mistaken for a valid XFL or a valid exponent. Most functions on this page validate their XFL arguments up front and return -10024 if the argument does not decode to a legal mantissa/exponent.
Because XFLs are opaque encoded integers, you never read the mantissa or exponent by shifting bits yourself — use float_mantissa, float_sign, and the arithmetic functions. To move a value between XFL form and the ledger wire format, use float_sto / float_sto_set. To turn an XFL into a plain integer (e.g. drops), use float_int.
Working with amounts: reading and comparing
Two idioms cover almost every hook that inspects a transaction amount.
1. Native XAH via AMOUNT_TO_DROPS. When the amount is native, the sfAmount field is 8 bytes of drops. The AMOUNT_TO_DROPS macro decodes those bytes to an integer number of drops without going through XFL at all — cheaper when you only need an integer comparison:
c
// Reject a native Payment below 10 XAH (10,000,000 drops).
uint8_t amt[48];
int64_t len = otxn_field((uint32_t)amt, sizeof(amt), sfAmount); // sfAmount = (6<<16)|1
if (len != 8)
rollback(SBUF("expected a native amount"), 1); // 8 bytes == native XAH
int64_t drops = AMOUNT_TO_DROPS(amt); // negative on error
if (drops < 0 || drops < 10000000LL)
rollback(SBUF("amount too small"), 2);
accept(SBUF("ok"), 0);2. IOU via float_sto_set + float_compare. For a token amount, decode the serialized Amount field into an XFL and compare against an XFL threshold:
c
// Reject an IOU Payment below a 100.0 threshold.
uint8_t amt[48];
int64_t len = otxn_field((uint32_t)amt, sizeof(amt), sfAmount);
if (len != 48)
rollback(SBUF("expected an IOU amount"), 1); // 48 bytes == IOU (8 + 20 + 20)
int64_t value = float_sto_set((uint32_t)amt, len);
int64_t threshold = float_set(0, 100); // 100.0
if (float_compare(value, threshold, COMPARE_LESS) == 1)
rollback(SBUF("amount below threshold"), 2);
accept(SBUF("ok"), 0);Percentage calculation. To take a percentage of an amount — for a fee, a reward split, etc. — scale the XFL with float_mulratio:
c
// Compute a 1.5% fee on an XFL amount, rounded down (15 / 1000).
int64_t fee = float_mulratio(amount, 0, 15, 1000);
if (fee < 0)
rollback(SBUF("fee calc failed"), fee);The number of bytes returned by otxn_field for sfAmount distinguishes the two cases at runtime: 8 for native XAH, 48 for an IOU (8-byte amount + 20-byte currency + 20-byte issuer).
Index
| Function | Purpose |
|---|---|
float_set | Build an XFL from an exponent and mantissa. |
float_one | The XFL constant 1.0. |
float_mantissa | Extract the mantissa of an XFL. |
float_sign | Extract the sign of an XFL. |
float_negate | Flip the sign of an XFL. |
float_sum | Add two XFLs. |
float_multiply | Multiply two XFLs. |
float_mulratio | Multiply an XFL by an integer ratio (numerator/denominator). |
float_divide | Divide one XFL by another. |
float_invert | Reciprocal 1/x of an XFL. |
float_compare | Compare two XFLs (equal / less / greater). |
float_log | Base-10 logarithm of an XFL. |
float_root | n-th root of an XFL. |
float_int | Convert an XFL to a scaled integer. |
float_sto | Serialize an XFL into an Amount STO field. |
float_sto_set | Parse an Amount STO back into an XFL. |
Related documents
- ../../README.md — documentation index.
- ../../overview.md — hook execution model.
- ../../glossary.md — full error-code and term reference (including the
INVALID_FLOAT = -10024andXFL_OVERFLOWentries). - ../../macros.md —
AMOUNT_TO_DROPS,SBUF,TRACEXFL, and the field-code helpers. - ../../best-practices.md — validating amounts and avoiding precision surprises.
- transaction.md —
otxn_fieldfor reading thesfAmountfield. - ledger-and-slot.md —
slot_floatreads a slotted amount directly as an XFL. - emit-and-etxn.md — building the amounts you serialize into emitted transactions.
- utility.md —
sto_subfieldand the other STO helpers. - ../../examples/payment-filter.md — a threshold-check hook end to end.