mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
test Sponsor Reserve checks for TrustSet
This commit is contained in:
@@ -451,6 +451,9 @@ areCompatible(
|
||||
beast::Journal::Stream& s,
|
||||
char const* reason);
|
||||
|
||||
uint32_t
|
||||
ownerCount(std::shared_ptr<SLE const> const& sponsorSle);
|
||||
|
||||
TER
|
||||
checkInsufficientReserve(
|
||||
ReadView const& view,
|
||||
|
||||
@@ -1029,6 +1029,18 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ownerCount(std::shared_ptr<SLE const> const& sponsorSle)
|
||||
{
|
||||
auto const ownerCount = sponsorSle->getFieldU32(sfOwnerCount);
|
||||
auto const sponsoredOwnerCount =
|
||||
sponsorSle->getFieldU32(sfSponsoredOwnerCount);
|
||||
auto const sponsoringOwnerCount =
|
||||
sponsorSle->getFieldU32(sfSponsoringOwnerCount);
|
||||
|
||||
return ownerCount + sponsoringOwnerCount - sponsoredOwnerCount;
|
||||
}
|
||||
|
||||
TER
|
||||
checkInsufficientReserve(
|
||||
ReadView const& view,
|
||||
@@ -1479,7 +1491,7 @@ authorizeMPToken(
|
||||
// an account owns, in the case of MPTokens we only
|
||||
// *enforce* a reserve if the user owns more than two
|
||||
// items. This is similar to the reserve requirements of trust lines.
|
||||
if (sleAcct->getFieldU32(sfOwnerCount) >= 2)
|
||||
if (ownerCount(sponsor.value_or(sleAcct)) >= 2)
|
||||
{
|
||||
if (auto const ret = checkInsufficientReserve(
|
||||
view, sleAcct, priorBalance, sponsor, 1);
|
||||
|
||||
@@ -47,10 +47,10 @@ adjustAccountXRPBalance(
|
||||
return;
|
||||
|
||||
if (currentBalance > balanceTo)
|
||||
env(pay(account, env.master, currentBalance - balanceTo + XRP(1)),
|
||||
env(pay(account, env.master, currentBalance - (balanceTo + XRP(1))),
|
||||
fee(XRP(1)));
|
||||
else
|
||||
env(pay(env.master, account, balanceTo - currentBalance), fee(XRP(1)));
|
||||
env(pay(env.master, account, balanceTo - currentBalance));
|
||||
|
||||
env.close();
|
||||
}
|
||||
@@ -1968,10 +1968,13 @@ public:
|
||||
env.close();
|
||||
|
||||
// for free mptoken checks
|
||||
std::uint32_t bobTicketSeq{env.seq(bob) + 1};
|
||||
env(ticket::create(bob, 2));
|
||||
adjustAccountXRPBalance(env, sponsor, reserve(env, 2));
|
||||
std::uint32_t ticketSeq{env.seq(sponsor) + 1};
|
||||
env(ticket::create(sponsor, 2));
|
||||
env.close();
|
||||
|
||||
adjustAccountXRPBalance(
|
||||
env, sponsor, reserve(env, 3) - drops(1));
|
||||
jv = {};
|
||||
jv[sfTransactionType] = jss::MPTokenAuthorize;
|
||||
jv[sfAccount] = bob.human();
|
||||
@@ -1983,9 +1986,12 @@ public:
|
||||
ter(tecINSUFFICIENT_RESERVE));
|
||||
env.close();
|
||||
|
||||
env(noop(bob), ticket::use(bobTicketSeq));
|
||||
env(noop(sponsor), ticket::use(ticketSeq));
|
||||
env.close();
|
||||
|
||||
adjustAccountXRPBalance(
|
||||
env, sponsor, reserve(env, 2) - drops(1));
|
||||
|
||||
// pass (free mptoken)
|
||||
env(jv,
|
||||
sponsor::as(sponsor, tfSponsorReserve),
|
||||
@@ -2822,71 +2828,112 @@ public:
|
||||
{
|
||||
testcase("TrustSet");
|
||||
using namespace test::jtx;
|
||||
Env env{*this, testable_amendments()};
|
||||
Account const alice("alice");
|
||||
Account const bob("bob");
|
||||
Account const sponsor("sponsor");
|
||||
Account const sponsor2("sponsor2");
|
||||
|
||||
env.fund(XRP(1000000), alice, bob, sponsor, sponsor2);
|
||||
env.close();
|
||||
|
||||
auto const& highAcc = alice > bob ? alice : bob;
|
||||
auto const& lowAcc = alice > bob ? bob : alice;
|
||||
for (bool isIssuerHigh : {false, true})
|
||||
{
|
||||
auto const& issuer = isIssuerHigh ? highAcc : lowAcc;
|
||||
auto const& user = isIssuerHigh ? lowAcc : highAcc;
|
||||
|
||||
auto const USD = issuer["USD"];
|
||||
|
||||
// create TrustLine
|
||||
env(trust(user, USD(100)),
|
||||
sponsor::as(sponsor, tfSponsorReserve),
|
||||
sponsor::sig(sponsor));
|
||||
Env env{*this, testable_amendments()};
|
||||
env.fund(XRP(1000000), alice, bob, sponsor, sponsor2);
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1);
|
||||
auto const& highAcc = alice > bob ? alice : bob;
|
||||
auto const& lowAcc = alice > bob ? bob : alice;
|
||||
for (bool isIssuerHigh : {false, true})
|
||||
{
|
||||
auto const& issuer = isIssuerHigh ? highAcc : lowAcc;
|
||||
auto const& user = isIssuerHigh ? lowAcc : highAcc;
|
||||
|
||||
auto const line = env.le(keylet::line(user, issuer, USD.currency));
|
||||
BEAST_EXPECT(
|
||||
line->getAccountID(
|
||||
isIssuerHigh ? sfLowSponsorAccount
|
||||
: sfHighSponsorAccount) == sponsor.id());
|
||||
BEAST_EXPECT(!line->isFieldPresent(
|
||||
isIssuerHigh ? sfHighSponsorAccount : sfLowSponsorAccount));
|
||||
auto const USD = issuer["USD"];
|
||||
|
||||
// transfer sponsor
|
||||
env(sponsor::transfer(
|
||||
user, keylet::line(user, issuer, USD.currency).key),
|
||||
sponsor::as(sponsor2, tfSponsorReserve),
|
||||
sponsor::sig(sponsor2));
|
||||
// create TrustLine
|
||||
env(trust(user, USD(100)),
|
||||
sponsor::as(sponsor, tfSponsorReserve),
|
||||
sponsor::sig(sponsor));
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1);
|
||||
|
||||
auto const line =
|
||||
env.le(keylet::line(user, issuer, USD.currency));
|
||||
BEAST_EXPECT(
|
||||
line->getAccountID(
|
||||
isIssuerHigh ? sfLowSponsorAccount
|
||||
: sfHighSponsorAccount) == sponsor.id());
|
||||
BEAST_EXPECT(!line->isFieldPresent(
|
||||
isIssuerHigh ? sfHighSponsorAccount : sfLowSponsorAccount));
|
||||
|
||||
// transfer sponsor
|
||||
env(sponsor::transfer(
|
||||
user, keylet::line(user, issuer, USD.currency).key),
|
||||
sponsor::as(sponsor2, tfSponsorReserve),
|
||||
sponsor::sig(sponsor2));
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1);
|
||||
|
||||
auto const line2 =
|
||||
env.le(keylet::line(user, issuer, USD.currency));
|
||||
BEAST_EXPECT(
|
||||
line2->getAccountID(
|
||||
isIssuerHigh ? sfLowSponsorAccount
|
||||
: sfHighSponsorAccount) == sponsor2.id());
|
||||
BEAST_EXPECT(!line2->isFieldPresent(
|
||||
isIssuerHigh ? sfHighSponsorAccount : sfLowSponsorAccount));
|
||||
|
||||
// delete TrustLine
|
||||
env(trust(user, USD(0)));
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 0);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 0);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
|
||||
|
||||
BEAST_EXPECT(!env.le(keylet::line(user, issuer, USD.currency)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// check INSUFFICIENT_RESERVE for TrustSet
|
||||
Env env{*this, testable_amendments()};
|
||||
env.fund(XRP(1000000), alice, bob, sponsor);
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 1);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1);
|
||||
auto const& highAcc = alice > bob ? alice : bob;
|
||||
auto const& lowAcc = alice > bob ? bob : alice;
|
||||
for (bool isIssuerHigh : {false})
|
||||
{
|
||||
auto const& issuer = isIssuerHigh ? highAcc : lowAcc;
|
||||
auto const& user = isIssuerHigh ? lowAcc : highAcc;
|
||||
auto const USD = issuer["USD"];
|
||||
|
||||
auto const line2 = env.le(keylet::line(user, issuer, USD.currency));
|
||||
BEAST_EXPECT(
|
||||
line2->getAccountID(
|
||||
isIssuerHigh ? sfLowSponsorAccount
|
||||
: sfHighSponsorAccount) == sponsor2.id());
|
||||
BEAST_EXPECT(!line2->isFieldPresent(
|
||||
isIssuerHigh ? sfHighSponsorAccount : sfLowSponsorAccount));
|
||||
adjustAccountXRPBalance(env, sponsor, reserve(env, 100));
|
||||
|
||||
// delete TrustLine
|
||||
env(trust(user, USD(0)));
|
||||
env.close();
|
||||
// free trustline
|
||||
std::uint32_t const ticketSeq{env.seq(sponsor) + 1};
|
||||
env(ticket::create(sponsor, 2));
|
||||
env.close();
|
||||
|
||||
BEAST_EXPECT(ownerCount(env, user) == 0);
|
||||
BEAST_EXPECT(sponsoredOwnerCount(env, user) == 0);
|
||||
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
|
||||
adjustAccountXRPBalance(
|
||||
env, sponsor, reserve(env, 3) - drops(1));
|
||||
|
||||
BEAST_EXPECT(!env.le(keylet::line(user, issuer, USD.currency)));
|
||||
// create TrustLine
|
||||
env(trust(user, USD(100)),
|
||||
sponsor::as(sponsor, tfSponsorReserve),
|
||||
sponsor::sig(sponsor),
|
||||
ter(tecNO_LINE_INSUF_RESERVE));
|
||||
env.close();
|
||||
|
||||
env(noop(sponsor), ticket::use(ticketSeq));
|
||||
env(noop(sponsor), ticket::use(ticketSeq + 1));
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -382,8 +382,6 @@ SetTrust::doApply()
|
||||
if (!sle)
|
||||
return tefINTERNAL;
|
||||
|
||||
std::uint32_t const uOwnerCount = sle->getFieldU32(sfOwnerCount);
|
||||
|
||||
// The reserve that is required to create the line. Note
|
||||
// that although the reserve increases with every item
|
||||
// an account owns, in the case of trust lines we only
|
||||
@@ -401,7 +399,13 @@ SetTrust::doApply()
|
||||
// but the incremental reserve for the trust line as
|
||||
// well. A person with no intention of using the gateway
|
||||
// could use the extra XRP for their own purposes.
|
||||
auto const txSponsorAcc = getTxReserveSponsorAccountID(ctx_.tx);
|
||||
|
||||
std::optional<std::shared_ptr<SLE>> txSponsorSle = std::nullopt;
|
||||
if (txSponsorAcc)
|
||||
txSponsorSle = view().peek(keylet::account(*txSponsorAcc));
|
||||
|
||||
std::uint32_t const uOwnerCount = ownerCount(txSponsorSle.value_or(sle));
|
||||
bool const freeTrustLine = uOwnerCount < 2;
|
||||
|
||||
std::uint32_t uQualityIn(bQualityIn ? ctx_.tx.getFieldU32(sfQualityIn) : 0);
|
||||
@@ -453,11 +457,6 @@ SetTrust::doApply()
|
||||
SLE::pointer sleRippleState =
|
||||
view().peek(keylet::line(account_, uDstAccountID, currency));
|
||||
|
||||
auto const txSponsorAcc = getTxReserveSponsorAccountID(ctx_.tx);
|
||||
std::optional<std::shared_ptr<SLE>> txSponsorSle = std::nullopt;
|
||||
if (txSponsorAcc)
|
||||
txSponsorSle = view().peek(keylet::account(*txSponsorAcc));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
STAmount saLowBalance;
|
||||
|
||||
Reference in New Issue
Block a user