Fix applyOffer() to use rate and other stuff.

This commit is contained in:
Arthur Britto
2013-01-25 14:23:42 -08:00
parent a2424396b3
commit d5477dc832
3 changed files with 61 additions and 44 deletions

View File

@@ -1007,15 +1007,26 @@ STAmount STAmount::setRate(uint64 rate)
return STAmount(CURRENCY_ONE, ACCOUNT_ONE, mantissa, exponent); return STAmount(CURRENCY_ONE, ACCOUNT_ONE, mantissa, exponent);
} }
// Taker gets all taker can pay for with saTakerFunds, limited by saOfferPays and saOfferFunds. // Taker gets all taker can pay for with saTakerFunds/uTakerPaysRate, limited by saOfferPays and saOfferFunds/uOfferPaysRate.
// --> uTakerPaysRate: >= QUALITY_ONE //
// --> uOfferPaysRate: >= QUALITY_ONE // Existing offer is on the books. Offer owner get's their rate.
// --> saOfferFunds: Limit for saOfferPays //
// Taker pays what they can. If taker is an offer, doesn't matter what rate taker is. Taker is spending at same or better rate
// than they wanted. Taker should consider themselves as wanting to buy X amount. Taker is willing to pay at most the rate of Y/X
// each. Therefore, after having some part of their offer fulfilled at a better rate their offer should be reduced accordingly.
//
// YYY Could have a flag for spend up to behaviour vs current limit spend rate.
//
// There are no quality costs for offer vs offer taking.
//
// --> uTakerPaysRate: >= QUALITY_ONE | TransferRate for third party IOUs paid by taker.
// --> uOfferPaysRate: >= QUALITY_ONE | TransferRate for third party IOUs paid by offer owner.
// --> saOfferRate: Original saOfferGets/saOfferPays, when offer was made.
// --> saOfferFunds: Limit for saOfferPays : How much can pay including fees.
// --> saTakerFunds: Limit for saOfferGets : How much taker really wants. : Driver // --> saTakerFunds: Limit for saOfferGets : How much taker really wants. : Driver
// --> saOfferPays: Request : this should be reduced as the offer is fullfilled. // --> saOfferPays: Request : this should be reduced as the offer is fullfilled.
// --> saOfferGets: Request : this should be reduced as the offer is fullfilled. // --> saOfferGets: Request : this should be reduced as the offer is fullfilled.
// --> saTakerPays: Total : Used to know the approximate ratio of the exchange. // --> saTakerGets: Limit for taker to get.
// --> saTakerGets: Total : Used to know the approximate ratio of the exchange.
// <-- saTakerPaid: Actual // <-- saTakerPaid: Actual
// <-- saTakerGot: Actual // <-- saTakerGot: Actual
// <-- saTakerIssuerFee: Actual // <-- saTakerIssuerFee: Actual
@@ -1023,62 +1034,63 @@ STAmount STAmount::setRate(uint64 rate)
// <-- bRemove: remove offer it is either fullfilled or unfunded // <-- bRemove: remove offer it is either fullfilled or unfunded
bool STAmount::applyOffer( bool STAmount::applyOffer(
const uint32 uTakerPaysRate, const uint32 uOfferPaysRate, const uint32 uTakerPaysRate, const uint32 uOfferPaysRate,
const STAmount& saOfferRate,
const STAmount& saOfferFunds, const STAmount& saTakerFunds, const STAmount& saOfferFunds, const STAmount& saTakerFunds,
const STAmount& saOfferPays, const STAmount& saOfferGets, const STAmount& saOfferPays, const STAmount& saOfferGets,
const STAmount& saTakerPays, const STAmount& saTakerGets, const STAmount& saTakerGets,
STAmount& saTakerPaid, STAmount& saTakerGot, STAmount& saTakerPaid, STAmount& saTakerGot,
STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee) STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee)
{ {
saOfferGets.throwComparable(saTakerPays); saOfferGets.throwComparable(saTakerFunds);
assert(!saOfferFunds.isZero() && !saTakerFunds.isZero()); // Must have funds. assert(!saOfferFunds.isZero() && !saTakerFunds.isZero()); // Must have funds.
assert(!saOfferGets.isZero() && !saOfferPays.isZero()); // Must not be a null offer. assert(!saOfferGets.isZero() && !saOfferPays.isZero()); // Must not be a null offer.
// Amount offer can pay out, limited by funds and fees. // Limit offerer funds available, by transfer fees.
STAmount saOfferFundsAvailable = QUALITY_ONE == uOfferPaysRate STAmount saOfferFundsAvailable = QUALITY_ONE == uOfferPaysRate
? saOfferFunds ? saOfferFunds
: STAmount::divide(saOfferFunds, STAmount(CURRENCY_ONE, uOfferPaysRate, -9)); : STAmount::divide(saOfferFunds, STAmount(CURRENCY_ONE, uOfferPaysRate, -9));
// Amount offer can pay out, limited by offer and funds. cLog(lsINFO) << "applyOffer: uOfferPaysRate=" << uOfferPaysRate;
STAmount saOfferPaysAvailable = std::min(saOfferFundsAvailable, saOfferPays); cLog(lsINFO) << "applyOffer: saOfferFundsAvailable=" << saOfferFundsAvailable.getFullText();
// Amount offer can get in proportion, limited by offer funds. // Limit taker funds available, by transfer fees.
STAmount saOfferGetsAvailable = STAmount saTakerFundsAvailable = QUALITY_ONE == uTakerPaysRate
saOfferFundsAvailable == saOfferPays ? saTakerFunds
? saOfferGets // Offer was fully funded, avoid shenanigans. : STAmount::divide(saTakerFunds, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
: divide(multiply(saTakerPays, saOfferPaysAvailable, CURRENCY_ONE, ACCOUNT_ONE), saTakerGets, saOfferGets.getCurrency(), saOfferGets.getIssuer());
// Amount taker can spend, limited by funds and fees. cLog(lsINFO) << "applyOffer: uTakerPaysRate=" << uTakerPaysRate;
STAmount saTakerFundsAvailable = QUALITY_ONE == uTakerPaysRate cLog(lsINFO) << "applyOffer: saTakerFundsAvailable=" << saTakerFundsAvailable.getFullText();
? saTakerFunds
: STAmount::divide(saTakerFunds, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
if (saOfferGets == saOfferGetsAvailable && saTakerFundsAvailable >= saOfferGets) STAmount saOfferPaysAvailable; // Amount offer can pay out, limited by offer and offerer funds.
STAmount saOfferGetsAvailable; // Amount offer would get, limited by offer funds.
if (saOfferFundsAvailable >= saOfferPays)
{ {
// Taker gets all of offer available. // Offer was fully funded, avoid math shenanigans.
saTakerPaid = saOfferGets; // Taker paid what offer could get.
saTakerGot = saOfferPays; // Taker got what offer could pay.
cLog(lsINFO) << "applyOffer: took all outright"; saOfferPaysAvailable = saOfferPays;
} saOfferGetsAvailable = saOfferGets;
else if (saTakerFunds >= saOfferGetsAvailable)
{
// Taker gets all of offer available.
saTakerPaid = saOfferGetsAvailable; // Taker paid what offer could get.
saTakerGot = saOfferPaysAvailable; // Taker got what offer could pay.
cLog(lsINFO) << "applyOffer: took all available";
} }
else else
{ {
// Taker only get's a portion of offer. // Offer has limited funding, limit offer gets and pays by funds available.
saTakerPaid = saTakerFunds; // Taker paid all he had. saOfferPaysAvailable = saOfferFundsAvailable;
saTakerGot = divide(multiply(saTakerFunds, saOfferPaysAvailable, CURRENCY_ONE, ACCOUNT_ONE), saOfferGetsAvailable, saOfferPays.getCurrency(), saOfferPays.getIssuer()); saOfferGetsAvailable = multiply(saOfferFundsAvailable, saOfferRate, saOfferGets);
cLog(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot.getFullText();
cLog(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable.getFullText();
} }
cLog(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferFundsAvailable.getFullText();
cLog(lsINFO) << "applyOffer: saOfferGetsAvailable=" << saOfferGetsAvailable.getFullText();
STAmount saTakerGetsAvailable = saTakerFunds >= saOfferGetsAvailable
? saTakerGets
: multiply(saTakerFunds, saOfferRate, saTakerGets); // Amount can afford.
saTakerGot = std::min(saTakerGets, saOfferPaysAvailable); // Limit by wanted and available.
saTakerPaid = saTakerGot == saOfferPaysAvailable
? saOfferGetsAvailable
: multiply(saTakerGot, saOfferRate, saTakerFunds);
if (uTakerPaysRate == QUALITY_ONE) if (uTakerPaysRate == QUALITY_ONE)
{ {
saTakerIssuerFee = STAmount(saTakerPaid.getCurrency(), saTakerPaid.getIssuer()); saTakerIssuerFee = STAmount(saTakerPaid.getCurrency(), saTakerPaid.getIssuer());
@@ -1088,7 +1100,7 @@ bool STAmount::applyOffer(
// Compute fees in a rounding safe way. // Compute fees in a rounding safe way.
STAmount saTotal = STAmount::multiply(saTakerPaid, STAmount(CURRENCY_ONE, uTakerPaysRate, -9)); STAmount saTotal = STAmount::multiply(saTakerPaid, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
saTakerIssuerFee = (saTotal > saTakerFunds) ? saTakerFunds-saTakerPaid : saTotal - saTakerPaid; saTakerIssuerFee = (saTotal > saTakerFunds) ? saTakerFunds-saTakerPaid : saTotal-saTakerPaid;
} }
if (uOfferPaysRate == QUALITY_ONE) if (uOfferPaysRate == QUALITY_ONE)
@@ -1100,9 +1112,11 @@ bool STAmount::applyOffer(
// Compute fees in a rounding safe way. // Compute fees in a rounding safe way.
STAmount saTotal = STAmount::multiply(saTakerGot, STAmount(CURRENCY_ONE, uOfferPaysRate, -9)); STAmount saTotal = STAmount::multiply(saTakerGot, STAmount(CURRENCY_ONE, uOfferPaysRate, -9));
saOfferIssuerFee = (saTotal > saOfferFunds) ? saOfferFunds-saTakerGot : saTotal - saTakerGot; saOfferIssuerFee = (saTotal > saOfferFunds) ? saOfferFunds-saTakerGot : saTotal-saTakerGot;
} }
cLog(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot.getFullText();
return saTakerGot >= saOfferPays; return saTakerGot >= saOfferPays;
} }

View File

@@ -147,6 +147,7 @@ TER OfferCreateTransactor::takeOffers(
STAmount saSubTakerGot; STAmount saSubTakerGot;
STAmount saTakerIssuerFee; STAmount saTakerIssuerFee;
STAmount saOfferIssuerFee; STAmount saOfferIssuerFee;
STAmount saOfferRate = STAmount::setRate(uTipQuality);
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText();
@@ -155,17 +156,18 @@ TER OfferCreateTransactor::takeOffers(
cLog(lsINFO) << "takeOffers: applyOffer: saPay: " << saPay.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saPay: " << saPay.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saOfferRate: " << saOfferRate.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
cLog(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText(); cLog(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText();
bool bOfferDelete = STAmount::applyOffer( bool bOfferDelete = STAmount::applyOffer(
mEngine->getNodes().rippleTransferRate(uTakerAccountID, uOfferOwnerID, uTakerPaysAccountID), mEngine->getNodes().rippleTransferRate(uTakerAccountID, uOfferOwnerID, uTakerPaysAccountID),
mEngine->getNodes().rippleTransferRate(uOfferOwnerID, uTakerAccountID, uTakerGetsAccountID), mEngine->getNodes().rippleTransferRate(uOfferOwnerID, uTakerAccountID, uTakerGetsAccountID),
saOfferRate,
saOfferFunds, saOfferFunds,
saPay, // Driver XXX need to account for fees. saPay,
saOfferPays, saOfferPays,
saOfferGets, saOfferGets,
saTakerPays,
saTakerGets, saTakerGets,
saSubTakerPaid, saSubTakerPaid,
saSubTakerGot, saSubTakerGot,

View File

@@ -373,9 +373,10 @@ public:
// And what's left of the offer? And how much do I actually pay? // And what's left of the offer? And how much do I actually pay?
static bool applyOffer( static bool applyOffer(
const uint32 uTakerPaysRate, const uint32 uOfferPaysRate, const uint32 uTakerPaysRate, const uint32 uOfferPaysRate,
const STAmount& saOfferRate,
const STAmount& saOfferFunds, const STAmount& saTakerFunds, const STAmount& saOfferFunds, const STAmount& saTakerFunds,
const STAmount& saOfferPays, const STAmount& saOfferGets, const STAmount& saOfferPays, const STAmount& saOfferGets,
const STAmount& saTakerPays, const STAmount& saTakerGets, const STAmount& saTakerGets,
STAmount& saTakerPaid, STAmount& saTakerGot, STAmount& saTakerPaid, STAmount& saTakerGot,
STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee); STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee);