add transfer rate

This commit is contained in:
Denis Angell
2023-01-24 05:43:35 -05:00
committed by Richard Holland
parent 4438ebb5b7
commit 0133a4136e
6 changed files with 469 additions and 147 deletions

View File

@@ -309,12 +309,13 @@ EscrowCreate::doApply()
// Create escrow in ledger. Note that we we use the value from the
// sequence or ticket. For more explanation see comments in SeqProxy.h.
Keylet const escrowKeylet = keylet::escrow(account, seqID(ctx_));
auto xferRate = transferRate(view(), amount.getIssuer());
Keylet const escrowKeylet =
keylet::escrow(account, ctx_.tx.getSeqProxy().value());
auto const slep = std::make_shared<SLE>(escrowKeylet);
(*slep)[sfAmount] = ctx_.tx[sfAmount];
(*slep)[sfAccount] = account;
(*slep)[sfTransferRate] = xferRate.value;
(*slep)[~sfCondition] = ctx_.tx[~sfCondition];
(*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
(*slep)[sfDestination] = ctx_.tx[sfDestination];
@@ -589,6 +590,13 @@ EscrowFinish::doApply()
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;
// perform a dry run of the transfer before we
// change anything on-ledger
TER result = trustTransferLockedBalance(
@@ -598,6 +606,7 @@ EscrowFinish::doApply()
sled, // dst account
amount, // xfer amount
-1,
lockedRate,
j_,
DryRun // dry run
);
@@ -636,6 +645,14 @@ EscrowFinish::doApply()
(*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
else
{
// compute transfer fee, if any
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
lockedRate = xferRate;
// all the significant complexity of checking the validity of this
// transfer and ensuring the lines exist etc is hidden away in this
// function, all we need to do is call it and return if unsuccessful.
@@ -646,6 +663,7 @@ EscrowFinish::doApply()
sled, // dst account
amount, // xfer amount
-1,
lockedRate,
j_,
WetRun // wet run;
);

View File

@@ -335,6 +335,7 @@ PayChanCreate::doApply()
STAmount const amount{ctx_.tx[sfAmount]};
bool isIssuer = amount.getIssuer() == account;
auto xferRate = transferRate(view(), amount.getIssuer());
// Create PayChan in ledger.
//
@@ -352,6 +353,7 @@ PayChanCreate::doApply()
(*slep)[sfAccount] = account;
(*slep)[sfDestination] = dst;
(*slep)[sfSettleDelay] = ctx_.tx[sfSettleDelay];
(*slep)[sfTransferRate] = xferRate.value;
(*slep)[sfPublicKey] = ctx_.tx[sfPublicKey];
(*slep)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
(*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
@@ -469,6 +471,19 @@ PayChanFund::doApply()
auto const txAccount = ctx_.tx[sfAccount];
auto const expiration = (*slep)[~sfExpiration];
bool isIssuer = amount.getIssuer() == txAccount;
// auto const chanFunds = (*slep)[sfAmount];
// adjust transfer rate
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate less than locked rate
if (xferRate < lockedRate)
(*slep)[sfTransferRate] = xferRate.value;
// throw if issuer rate greater than locked rate
if (xferRate > lockedRate)
return temBAD_TRANSFER_RATE;
// if this is a Fund operation on an IOU then perform a dry run here
if (!isXRP(amount) &&
ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
@@ -728,6 +743,17 @@ PayChanClaim::doApply()
}
}
// compute transfer fee, if any
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = chanFunds.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
{
(*slep)[sfTransferRate] = xferRate.value;
lockedRate = xferRate;
}
(*slep)[sfBalance] = ctx_.tx[sfBalance];
STAmount const reqDelta = reqBalance - chanBalance;
assert(reqDelta >= beast::zero);
@@ -749,6 +775,7 @@ PayChanClaim::doApply()
sled,
reqDelta,
0,
lockedRate,
ctx_.journal,
WetRun);

View File

@@ -490,7 +490,6 @@ trustAdjustLockedBalance(
// dry runs are explicit in code, but really the view type determines
// what occurs here, so this combination is invalid.
static_assert(!(std::is_same<V, ReadView const>::value && !dryRun));
if (!view.rules().enabled(featurePaychanAndEscrowForTokens))
@@ -772,6 +771,7 @@ trustTransferLockedBalance(
S& sleDstAcc,
STAmount const& amount, // issuer, currency are in this field
int deltaLockCount, // -1 decrement, +1 increment, 0 unchanged
Rate const& xferRate, // TransferRate
beast::Journal const& j,
R dryRun)
{
@@ -829,7 +829,7 @@ trustTransferLockedBalance(
Keylet klSrcLine{keylet::line(srcAccID, issuerAccID, currency)};
SLEPtr sleSrcLine = peek(klSrcLine);
// source account IS issuer
// source account is not issuer use locked balance
if (!isIssuer)
{
if (!sleSrcLine)
@@ -919,16 +919,18 @@ trustTransferLockedBalance(
// dstLow XNOR srcLow tells us if we need to flip the balance amount
// on the destination line
bool flipDstAmt = !((dstHigh && srcHigh) || (!dstHigh && !srcHigh));
// compute transfer fee, if any
auto xferRate = transferRate(view, issuerAccID);
// the destination will sometimes get less depending on xfer rate
// with any difference in tokens burned
auto dstAmt = xferRate == parityRate
? amount
: multiplyRound(amount, xferRate, amount.issue(), true);
// default to amount
auto dstAmt = amount;
// if transfer rate
if (xferRate != parityRate)
{
// compute transfer fee, if any
auto const xferFee =
amount.value() - divideRound(amount, xferRate, amount.issue(), true);
// compute balance to transfer
dstAmt = amount.value() - xferFee;
}
// check for a destination line
Keylet klDstLine = keylet::line(dstAccID, issuerAccID, currency);
SLEPtr sleDstLine = peek(klDstLine);
@@ -945,7 +947,6 @@ trustTransferLockedBalance(
if (std::uint32_t const ownerCount = {sleDstAcc->at(sfOwnerCount)};
dstBalanceDrops < view.fees().accountReserve(ownerCount + 1))
return tecNO_LINE_INSUF_RESERVE;
// yes we can... we will
auto const finalDstAmt =

View File

@@ -123,15 +123,16 @@ LedgerFormats::LedgerFormats()
{sfAccount, soeREQUIRED},
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED},
{sfTransferRate, soeREQUIRED},
{sfCondition, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfFinishAfter, soeOPTIONAL},
{sfSourceTag, soeOPTIONAL},
{sfDestinationTag, soeOPTIONAL},
{sfDestinationNode, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDestinationNode, soeOPTIONAL},
},
commonFields);
@@ -232,14 +233,15 @@ LedgerFormats::LedgerFormats()
{sfBalance, soeREQUIRED},
{sfPublicKey, soeREQUIRED},
{sfSettleDelay, soeREQUIRED},
{sfTransferRate, soeREQUIRED},
{sfExpiration, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfSourceTag, soeOPTIONAL},
{sfDestinationTag, soeOPTIONAL},
{sfDestinationNode, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDestinationNode, soeOPTIONAL},
},
commonFields);