Merge branch 'develop' into pratik/Add-sanitizers-to-CI-builds

This commit is contained in:
Pratik Mankawde
2025-11-12 10:37:48 +00:00
2 changed files with 86 additions and 5 deletions

View File

@@ -2885,7 +2885,7 @@ assetsToSharesDeposit(
.truncate()};
Number const shareTotal = issuance->at(sfOutstandingAmount);
shares = (shareTotal * (assets / assetTotal)).truncate();
shares = ((shareTotal * assets) / assetTotal).truncate();
return shares;
}
@@ -2914,7 +2914,7 @@ sharesToAssetsDeposit(
false};
Number const shareTotal = issuance->at(sfOutstandingAmount);
assets = assetTotal * (shares / shareTotal);
assets = (assetTotal * shares) / shareTotal;
return assets;
}
@@ -2940,7 +2940,7 @@ assetsToSharesWithdraw(
if (assetTotal == 0)
return shares;
Number const shareTotal = issuance->at(sfOutstandingAmount);
Number result = shareTotal * (assets / assetTotal);
Number result = (shareTotal * assets) / assetTotal;
if (truncate == TruncateShares::yes)
result = result.truncate();
shares = result;
@@ -2968,7 +2968,7 @@ sharesToAssetsWithdraw(
if (assetTotal == 0)
return assets;
Number const shareTotal = issuance->at(sfOutstandingAmount);
assets = assetTotal * (shares / shareTotal);
assets = (assetTotal * shares) / shareTotal;
return assets;
}

View File

@@ -2454,6 +2454,7 @@ class Vault_test : public beast::unit_test::suite
struct CaseArgs
{
int initialXRP = 1000;
Number initialIOU = 200;
double transferRate = 1.0;
};
@@ -2481,7 +2482,7 @@ class Vault_test : public beast::unit_test::suite
PrettyAsset const asset = issuer["IOU"];
env.trust(asset(1000), owner);
env.trust(asset(1000), charlie);
env(pay(issuer, owner, asset(200)));
env(pay(issuer, owner, asset(args.initialIOU)));
env(rate(issuer, args.transferRate));
env.close();
@@ -2859,6 +2860,86 @@ class Vault_test : public beast::unit_test::suite
env(tx1);
});
testCase(
[&, this](
Env& env,
Account const& owner,
Account const& issuer,
Account const& charlie,
auto const& vaultAccount,
Vault& vault,
PrettyAsset const& asset,
auto&&...) {
testcase("IOU calculation rounding");
auto [tx, keylet] =
vault.create({.owner = owner, .asset = asset});
tx[sfScale] = 1;
env(tx);
env.close();
auto const startingOwnerBalance = env.balance(owner, asset);
BEAST_EXPECT(
(startingOwnerBalance.value() ==
STAmount{asset, 11875, -2}));
// This operation (first deposit 100, then 3.75 x 5) is known to
// have triggered calculation rounding errors in Number
// (addition and division), causing the last deposit to be
// blocked by Vault invariants.
env(vault.deposit(
{.depositor = owner,
.id = keylet.key,
.amount = asset(100)}));
auto const tx1 = vault.deposit(
{.depositor = owner,
.id = keylet.key,
.amount = asset(Number(375, -2))});
for (auto i = 0; i < 5; ++i)
{
env(tx1);
}
env.close();
{
STAmount const xfer{asset, 1185, -1};
BEAST_EXPECT(
env.balance(owner, asset) ==
startingOwnerBalance.value() - xfer);
BEAST_EXPECT(
env.balance(vaultAccount(keylet), asset) == xfer);
auto const vault = env.le(keylet);
BEAST_EXPECT(vault->at(sfAssetsAvailable) == xfer);
BEAST_EXPECT(vault->at(sfAssetsTotal) == xfer);
}
// Total vault balance should be 118.5 IOU. Withdraw and delete
// the vault to verify this exact amount was deposited and the
// owner has matching shares
env(vault.withdraw(
{.depositor = owner,
.id = keylet.key,
.amount = asset(Number(1000 + 37 * 5, -1))}));
{
BEAST_EXPECT(
env.balance(owner, asset) ==
startingOwnerBalance.value());
BEAST_EXPECT(
env.balance(vaultAccount(keylet), asset) ==
beast::zero);
auto const vault = env.le(keylet);
BEAST_EXPECT(vault->at(sfAssetsAvailable) == beast::zero);
BEAST_EXPECT(vault->at(sfAssetsTotal) == beast::zero);
}
env(vault.del({.owner = owner, .id = keylet.key}));
env.close();
},
{.initialIOU = Number(11875, -2)});
auto const [acctReserve, incReserve] = [this]() -> std::pair<int, int> {
Env env{*this, testable_amendments()};
return {