Skip to content

Examples of Rounding Issues

Elliot. edited this page Jul 3, 2025 · 1 revision
  1. Make two buy offers from two different accounts.
  2. Make one counter-offer (sell) from a another (third) account.

Based on account balances and the rules of how people assume matching on XRPL works, they may think that the orders should have matched, while they do not.

Here is a unit-test to replicate this issue. The cause is in the tfSell flag on the sell offer, which produces a result with a slightly worse quality than the sell offer. If tfSell is set, then the entire TakerGets amount is going to be exchanged, even if it means obtaining more than TakerPays. A sell offer is executed by the payment engine with the output set to a very large amount since we want to accept more than TakerPays but we don't know upfront what this amount should be. The quality which gets calculated in the following case is 1,000.13 AAA / 120.0155999999999 BBB. This is worse quality than the sell offer. Consequently, the offer is not crossed. This happens due to the rounding, which results in BBB being off by 10**-13. If tfSell flag is removed, then the payment engine generates exactly what the sell offer is asking: 1,000.13 AAA / 120.0156 BBB, and the offers cross.

Account const gw("gw");
Account const alice("alice");
Account const carol("carol");
Account const bob("bob");
Env env(*this);
auto pay_ = [&](auto& env,
                auto const& src,
                std::vector<AccountID> const& accts,
                auto const& amt) {
        for (auto const& dst : accts)
        env(pay(src, dst, amt));
};
env.fund(XRP(1'000), gw, alice, carol, bob);
auto const AAA = gw["AAA"];
auto const BBB = gw["BBB"];
env(trust(alice, AAA(2'000)));
env(trust(carol, AAA(2'000)));
env(trust(bob, AAA(2'000)));
env(trust(alice, BBB(2'000)));
env(trust(carol, BBB(2'000)));
env(trust(bob, BBB(2'000)));
pay_(env, gw, {alice, carol, bob}, AAA(1'200));
pay_(env, gw, {alice, carol, bob}, BBB(1'200));
env(offer(alice, AAA(50), BBB(6)));
env(offer(carol, AAA(1'000.01), BBB(120.0012)));
env(offer(bob, BBB(120.0156), AAA(1'000.13)), txflags(tfSell));

The worse quality is due to the rounding.

Clone this wiki locally