Merge branch 'ximinez/lending-refactoring-2' into ximinez/lending-refactoring-3

This commit is contained in:
Ed Hennis
2025-07-29 20:33:40 -04:00
committed by GitHub
3 changed files with 94 additions and 0 deletions

View File

@@ -32,6 +32,7 @@
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (AMMClawbackRounding, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -21,6 +21,7 @@
#include <test/jtx/WSClient.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/protocol/jss.h>
namespace ripple {
@@ -329,12 +330,95 @@ class DeliveredAmount_test : public beast::unit_test::suite
}
}
void
testMPTDeliveredAmountRPC(FeatureBitset features)
{
testcase("MPT DeliveredAmount");
using namespace jtx;
Account const alice("alice");
Account const carol("carol");
Account const bob("bob");
Env env{*this, features};
MPTTester mptAlice(
env, alice, {.holders = {bob, carol}, .close = false});
mptAlice.create(
{.transferFee = 25000,
.ownerCount = 1,
.holderCount = 0,
.flags = tfMPTCanTransfer});
auto const MPT = mptAlice["MPT"];
mptAlice.authorize({.account = bob});
mptAlice.authorize({.account = carol});
// issuer to holder
mptAlice.pay(alice, bob, 10000);
// holder to holder
env(pay(bob, carol, mptAlice.mpt(1000)), txflags(tfPartialPayment));
env.close();
// Get the hash for the most recent transaction.
std::string txHash{
env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
Json::Value meta = env.rpc("tx", txHash)[jss::result][jss::meta];
if (features[fixMPTDeliveredAmount])
{
BEAST_EXPECT(
meta[sfDeliveredAmount.jsonName] ==
STAmount{MPT(800)}.getJson(JsonOptions::none));
BEAST_EXPECT(
meta[jss::delivered_amount] ==
STAmount{MPT(800)}.getJson(JsonOptions::none));
}
else
{
BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName));
BEAST_EXPECT(
meta[jss::delivered_amount] = Json::Value("unavailable"));
}
env(pay(bob, carol, MPT(1000)),
sendmax(MPT(1200)),
txflags(tfPartialPayment));
env.close();
txHash = env.tx()->getJson(JsonOptions::none)[jss::hash].asString();
meta = env.rpc("tx", txHash)[jss::result][jss::meta];
if (features[fixMPTDeliveredAmount])
{
BEAST_EXPECT(
meta[sfDeliveredAmount.jsonName] ==
STAmount{MPT(960)}.getJson(JsonOptions::none));
BEAST_EXPECT(
meta[jss::delivered_amount] ==
STAmount{MPT(960)}.getJson(JsonOptions::none));
}
else
{
BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName));
BEAST_EXPECT(
meta[jss::delivered_amount] = Json::Value("unavailable"));
}
}
public:
void
run() override
{
using namespace test::jtx;
FeatureBitset const all{testable_amendments()};
testTxDeliveredAmountRPC();
testAccountDeliveredAmountSubscribe();
testMPTDeliveredAmountRPC(all - fixMPTDeliveredAmount);
testMPTDeliveredAmountRPC(all);
}
};

View File

@@ -585,7 +585,16 @@ Payment::doApply()
auto res = accountSend(
pv, account_, dstAccountID, amountDeliver, ctx_.journal);
if (res == tesSUCCESS)
{
pv.apply(ctx_.rawView());
// If the actual amount delivered is different from the original
// amount due to partial payment or transfer fee, we need to update
// DelieveredAmount using the actual delivered amount
if (view().rules().enabled(fixMPTDeliveredAmount) &&
amountDeliver != dstAmount)
ctx_.deliver(amountDeliver);
}
else if (res == tecINSUFFICIENT_FUNDS || res == tecPATH_DRY)
res = tecPATH_PARTIAL;