
Partial payments
4 minDifficulty Checked 2026-11-10- With the partial payment flag, a payment may deliver less than its stated amount and still succeed.
- The delivered_amount field in the metadata shows what arrived.
- Crediting the Amount field instead of delivered_amount is a known way to get robbed.
A normal payment is a promise: deliver exactly this much or fail. The sender covers any exchange cost on the way.
A partial payment flips that. The sender says: spend up to this much of mine, and deliver whatever is left after costs. The amount written on the payment becomes a ceiling, not a promise.
This has an honest use. Say a shop gets a payment it cannot match to an order and wants to send it back. With a partial payment the shop returns what it received and does not pay extra to cover exchange costs.
It also has a dishonest use. A scammer sends a payment labeled "10,000" with the partial flag set. It delivers a tiny fraction of that. The transaction still says success. A careless shop or exchange reads the label, credits 10,000 and gets robbed.
The fix is one habit. Never read the label. Read the receipt. Every successful payment records a field called delivered_amount. It states what arrived. That is the number to trust.
Two limits help ordinary users. A plain XRP-to-XRP payment can never be partial. A partial payment also cannot fund a new account. The risk sits with token payments and payments that convert currency.
If someone shows you a payment as proof they paid, look at the delivered amount on an explorer yourself.
A partial payment is any Payment with tfPartialPayment (0x00020000, decimal 131072) set.
Without the flag. Amount is the exact amount to deliver. SendMax caps the cost. If the full amount cannot be delivered within SendMax, the transaction fails.
Amount + fees = sent amount ≤ SendMax
With the flag. Amount is the most to deliver. The payment succeeds if it delivers any positive amount, or at least DeliverMin when that optional field is set.
Amount ≥ delivered amount ≥ DeliverMin > 0
"Fees" here means transfer fees and exchange rates. The XRP transaction cost in Fee is separate and is always destroyed.
Limits.
- Direct XRP-to-XRP payments cannot be partial:
temBAD_SEND_XRP_PARTIAL. - A partial payment cannot fund a new address:
telNO_DST_PARTIAL. - Cross-currency payments with XRP on one side can be partial.
delivered_amount. Metadata of a successful Payment includes delivered_amount, in the same format as Amount. Where to read it:
| Method | Field |
|---|---|
tx | result.meta.delivered_amount |
account_tx | meta.delivered_amount on each transaction |
subscribe transaction streams | meta.delivered_amount |
For non-partial payments it equals Amount, apart from rounding on token deliveries. For partial payments validated before 2014-01-20 it is the string unavailable.
The rename. API v2 renamed Amount to DeliverMax on Payment, starting with rippled 2.0.0. The new name says what the field means and makes the mistake harder to make.
The exploit, step by step. An attacker sends a large Amount with tfPartialPayment. The payment returns tesSUCCESS and delivers a tiny amount. The victim's software reads Amount, credits the full figure, and the attacker withdraws it. Reading delivered_amount is enough to stop it.
Bouncing. To return a payment, the docs suggest a partial payment with Amount set to what was received and no SendMax. Copy the incoming SourceTag into DestinationTag.
Related: Destination tags, Cross-currency payments and paths.
- Partial PaymentsRead 2026-11-10
- PaymentRead 2026-11-10
- Bouncing PaymentsRead 2026-11-10
