mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-27 05:55:50 +00:00
fix finalAmount + guard dest Issuer
This commit is contained in:
committed by
Richard Holland
parent
31da4bf8d4
commit
f8591d0fd6
@@ -811,7 +811,8 @@ trustTransferLockedBalance(
|
|||||||
|
|
||||||
bool srcHigh = srcAccID > issuerAccID;
|
bool srcHigh = srcAccID > issuerAccID;
|
||||||
bool dstHigh = dstAccID > issuerAccID;
|
bool dstHigh = dstAccID > issuerAccID;
|
||||||
bool isIssuer = issuerAccID == srcAccID;
|
bool srcIssuer = issuerAccID == srcAccID;
|
||||||
|
bool dstIssuer = issuerAccID == dstAccID;
|
||||||
|
|
||||||
// check for freezing, auth, no ripple and TL sanity
|
// check for freezing, auth, no ripple and TL sanity
|
||||||
{
|
{
|
||||||
@@ -825,13 +826,36 @@ trustTransferLockedBalance(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dstLow XNOR srcLow tells us if we need to flip the balance amount
|
||||||
|
// on the destination line
|
||||||
|
bool flipDstAmt = !((dstHigh && srcHigh) || (!dstHigh && !srcHigh));
|
||||||
|
|
||||||
|
// default dstAmount to amount
|
||||||
|
auto dstAmt = amount;
|
||||||
|
|
||||||
|
// if tx acct not source issuer or dest issuer
|
||||||
|
// and xfer rate is not parity
|
||||||
|
if ((!srcIssuer || !dstIssuer) && lXferRate != parityRate)
|
||||||
|
{
|
||||||
|
// compute transfer fee, if any
|
||||||
|
auto const xferFee = amount.value() -
|
||||||
|
divideRound(
|
||||||
|
amount,
|
||||||
|
lXferRate,
|
||||||
|
amount.issue(),
|
||||||
|
true);
|
||||||
|
// compute balance to transfer
|
||||||
|
dstAmt = amount.value() - xferFee;
|
||||||
|
}
|
||||||
|
|
||||||
// ensure source line exists
|
// ensure source line exists
|
||||||
Keylet klSrcLine{keylet::line(srcAccID, issuerAccID, currency)};
|
Keylet klSrcLine{keylet::line(srcAccID, issuerAccID, currency)};
|
||||||
SLEPtr sleSrcLine = peek(klSrcLine);
|
SLEPtr sleSrcLine = peek(klSrcLine);
|
||||||
|
|
||||||
// source account is not issuer use locked balance
|
// if source account is not issuer
|
||||||
if (!isIssuer)
|
if (!srcIssuer)
|
||||||
{
|
{
|
||||||
|
// if source account has no trust line - fail
|
||||||
if (!sleSrcLine)
|
if (!sleSrcLine)
|
||||||
return tecNO_LINE;
|
return tecNO_LINE;
|
||||||
|
|
||||||
@@ -916,28 +940,17 @@ trustTransferLockedBalance(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dstLow XNOR srcLow tells us if we need to flip the balance amount
|
|
||||||
// on the destination line
|
|
||||||
bool flipDstAmt = !((dstHigh && srcHigh) || (!dstHigh && !srcHigh));
|
|
||||||
|
|
||||||
// default to amount
|
|
||||||
auto dstAmt = amount;
|
|
||||||
// if transfer rate
|
|
||||||
if (lXferRate != parityRate)
|
|
||||||
{
|
|
||||||
// compute transfer fee, if any
|
|
||||||
auto const xferFee = amount.value() -
|
|
||||||
divideRound(amount, lXferRate, amount.issue(), true);
|
|
||||||
// compute balance to transfer
|
|
||||||
dstAmt = amount.value() - xferFee;
|
|
||||||
}
|
|
||||||
// check for a destination line
|
// check for a destination line
|
||||||
Keylet klDstLine = keylet::line(dstAccID, issuerAccID, currency);
|
Keylet klDstLine = keylet::line(dstAccID, issuerAccID, currency);
|
||||||
SLEPtr sleDstLine = peek(klDstLine);
|
SLEPtr sleDstLine = peek(klDstLine);
|
||||||
|
|
||||||
|
// if dest account is not issuer
|
||||||
|
if (!dstIssuer)
|
||||||
|
{
|
||||||
|
// if dest acct has no trustline
|
||||||
if (!sleDstLine)
|
if (!sleDstLine)
|
||||||
{
|
{
|
||||||
// in most circumstances a missing destination line is a deal breaker
|
// if tx acct is not dest acct and src acct is not dest acct
|
||||||
if (actingAccID != dstAccID && srcAccID != dstAccID)
|
if (actingAccID != dstAccID && srcAccID != dstAccID)
|
||||||
return tecNO_LINE;
|
return tecNO_LINE;
|
||||||
|
|
||||||
@@ -947,10 +960,10 @@ trustTransferLockedBalance(
|
|||||||
if (std::uint32_t const ownerCount = {sleDstAcc->at(sfOwnerCount)};
|
if (std::uint32_t const ownerCount = {sleDstAcc->at(sfOwnerCount)};
|
||||||
dstBalanceDrops < view.fees().accountReserve(ownerCount + 1))
|
dstBalanceDrops < view.fees().accountReserve(ownerCount + 1))
|
||||||
return tecNO_LINE_INSUF_RESERVE;
|
return tecNO_LINE_INSUF_RESERVE;
|
||||||
// yes we can... we will
|
|
||||||
|
|
||||||
auto const finalDstAmt =
|
// compute final destination amount
|
||||||
isIssuer ? dstAmt : flipDstAmt ? -dstAmt : dstAmt;
|
auto const finalDstAmt = flipDstAmt ? -dstAmt : dstAmt;
|
||||||
|
// create destination trust line
|
||||||
if constexpr (!dryRun)
|
if constexpr (!dryRun)
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@@ -978,18 +991,21 @@ trustTransferLockedBalance(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// the dst line does exist, and it would have been checked above
|
// dest trust line does exist
|
||||||
// in trustTransferAllowed for NoRipple and Freeze flags
|
// checked NoRipple and Freeze flags in trustTransferAllowed
|
||||||
|
|
||||||
// check the limit
|
// check the limit
|
||||||
STAmount dstLimit =
|
STAmount dstLimit =
|
||||||
dstHigh ? (*sleDstLine)[sfHighLimit] : (*sleDstLine)[sfLowLimit];
|
dstHigh ? (*sleDstLine)[sfHighLimit] : (*sleDstLine)[sfLowLimit];
|
||||||
|
|
||||||
|
// get prior balance
|
||||||
STAmount priorBalance =
|
STAmount priorBalance =
|
||||||
dstHigh ? -((*sleDstLine)[sfBalance]) : (*sleDstLine)[sfBalance];
|
dstHigh ? -((*sleDstLine)[sfBalance]) : (*sleDstLine)[sfBalance];
|
||||||
|
|
||||||
|
// combine prior with dest amount for final
|
||||||
STAmount finalBalance = priorBalance + dstAmt;
|
STAmount finalBalance = priorBalance + dstAmt;
|
||||||
|
|
||||||
|
// if final is less than prior - fail
|
||||||
if (finalBalance < priorBalance)
|
if (finalBalance < priorBalance)
|
||||||
{
|
{
|
||||||
JLOG(j.warn()) << "trustTransferLockedBalance resulted in a "
|
JLOG(j.warn()) << "trustTransferLockedBalance resulted in a "
|
||||||
@@ -997,6 +1013,7 @@ trustTransferLockedBalance(
|
|||||||
return tecINTERNAL;
|
return tecINTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if final is more than dest limit and tx acct is not dest acct - fail
|
||||||
if (finalBalance > dstLimit && actingAccID != dstAccID)
|
if (finalBalance > dstLimit && actingAccID != dstAccID)
|
||||||
{
|
{
|
||||||
JLOG(j.trace()) << "trustTransferLockedBalance would increase dest "
|
JLOG(j.trace()) << "trustTransferLockedBalance would increase dest "
|
||||||
@@ -1004,26 +1021,30 @@ trustTransferLockedBalance(
|
|||||||
return tecPATH_DRY;
|
return tecPATH_DRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there is significant precision loss
|
// if there is significant precision loss - fail
|
||||||
if (!isAddable(priorBalance, dstAmt))
|
if (!isAddable(priorBalance, dstAmt))
|
||||||
return tecPRECISION_LOSS;
|
return tecPRECISION_LOSS;
|
||||||
|
|
||||||
finalBalance =
|
// compute final balance to send - reverse sign for high dest
|
||||||
isIssuer ? -finalBalance : dstHigh ? -finalBalance : finalBalance;
|
finalBalance = dstHigh ? -finalBalance : finalBalance;
|
||||||
|
|
||||||
|
// if not dry run - set dst line field
|
||||||
if constexpr (!dryRun)
|
if constexpr (!dryRun)
|
||||||
sleDstLine->setFieldAmount(sfBalance, finalBalance);
|
sleDstLine->setFieldAmount(sfBalance, finalBalance);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if constexpr (!dryRun)
|
if constexpr (!dryRun)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<V, ApplyView>::value);
|
static_assert(std::is_same<V, ApplyView>::value);
|
||||||
|
|
||||||
// check if source line ended up in default state and adjust owner count
|
// if source account is not issuer
|
||||||
// if it did
|
if (!srcIssuer)
|
||||||
if (!isIssuer)
|
|
||||||
{
|
{
|
||||||
|
// check if source line ended up in default state
|
||||||
if (isTrustDefault(sleSrcAcc, sleSrcLine))
|
if (isTrustDefault(sleSrcAcc, sleSrcLine))
|
||||||
{
|
{
|
||||||
|
// adjust owner count
|
||||||
uint32_t flags = sleSrcLine->getFieldU32(sfFlags);
|
uint32_t flags = sleSrcLine->getFieldU32(sfFlags);
|
||||||
uint32_t fReserve{srcHigh ? lsfHighReserve : lsfLowReserve};
|
uint32_t fReserve{srcHigh ? lsfHighReserve : lsfLowReserve};
|
||||||
if (flags & fReserve)
|
if (flags & fReserve)
|
||||||
@@ -1033,11 +1054,13 @@ trustTransferLockedBalance(
|
|||||||
view.update(sleSrcAcc);
|
view.update(sleSrcAcc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// update source line
|
||||||
view.update(sleSrcLine);
|
view.update(sleSrcLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a destination line already existed and was updated
|
// if dest line exists
|
||||||
if (sleDstLine)
|
if (sleDstLine)
|
||||||
|
// update dest line
|
||||||
view.update(sleDstLine);
|
view.update(sleDstLine);
|
||||||
}
|
}
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user