mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 14:20:56 +00:00
fix: Add VaultInvariant check that lossUnrealized is non-negative (#7863)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
This commit is contained in:
@@ -483,6 +483,12 @@ ValidVault::finalize(
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (view.rules().enabled(fixCleanup3_4_0) && afterVault.lossUnrealized < kZero)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: loss unrealized must not be negative";
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (afterVault.assetsTotal < kZero)
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: assets outstanding must be positive";
|
||||
|
||||
@@ -3374,6 +3374,41 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
precloseXrp,
|
||||
TxAccount::A2);
|
||||
|
||||
// A negative loss unrealized must trip the invariant. ttLOAN_MANAGE is
|
||||
// allowed to change loss unrealized, so it isolates this check from the
|
||||
// "must not change loss unrealized" invariant. Gated behind
|
||||
// fixCleanup3_4_0 (see below).
|
||||
doInvariantCheck(
|
||||
{"loss unrealized must not be negative"},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
auto const keylet = keylet::vault(a1.id(), ac.view().seq());
|
||||
return kAdjust(ac.view(), keylet, kArgs(a2.id(), 0, [&](Adjustments& sample) {
|
||||
sample.lossUnrealized = -1;
|
||||
}));
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttLOAN_MANAGE, [](STObject& tx) {}},
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED},
|
||||
precloseXrp,
|
||||
TxAccount::A2);
|
||||
|
||||
// Without fixCleanup3_4_0 the same state must NOT trip the invariant,
|
||||
// preserving pre-amendment behavior (no fork risk).
|
||||
doInvariantCheck(
|
||||
makeEnv(defaultAmendments() - fixCleanup3_4_0),
|
||||
{},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
auto const keylet = keylet::vault(a1.id(), ac.view().seq());
|
||||
return kAdjust(ac.view(), keylet, kArgs(a2.id(), 0, [&](Adjustments& sample) {
|
||||
sample.lossUnrealized = -1;
|
||||
}));
|
||||
},
|
||||
XRPAmount{},
|
||||
STTx{ttLOAN_MANAGE, [](STObject& tx) {}},
|
||||
{tesSUCCESS, tesSUCCESS},
|
||||
precloseXrp,
|
||||
TxAccount::A2);
|
||||
|
||||
doInvariantCheck(
|
||||
{"set assets outstanding must not exceed assets maximum"},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
|
||||
Reference in New Issue
Block a user