Gelalens

Market Prices

Coin Price 24h
BTC Bitcoin
$76,050 -1.15%
ETH Ethereum
$2,412.77 -2.57%
SOL Solana
$97.61 -2.90%
BNB BNB Chain
$713.2 -0.70%
XRP XRP Ledger
$1.29 -7.41%
DOGE Dogecoin
$0.0801 -2.77%
ADA Cardano
$0.1947 -4.56%
AVAX Avalanche
$7.29 -2.29%
DOT Polkadot
$0.9592 -2.88%
LINK Chainlink
$10.85 -4.29%

Fear & Greed

51

Neutral

Market Sentiment

Event Calendar

{{年份}}
18
03
unlock Sui Token Unlock

Team and early investor shares released

28
03
unlock Arbitrum Token Unlock

92 million ARB released

15
04
halving Bitcoin Halving

Block reward reduced to 3.125 BTC

30
04
upgrade Celestia Mainnet Upgrade

Improves data availability sampling efficiency

12
05
halving BCH Halving

Block reward halving event

08
04
upgrade Solana Firedancer

Independent validator client goes live on mainnet

10
05
upgrade Ethereum Pectra Upgrade

Raises validator limit and account abstraction

22
03
unlock Optimism Unlock

Circulating supply increases by about 2%

Altseason Index

41

Bitcoin Season

BTC Dominance Altseason

Gas Tracker

Ethereum 28 Gwei
BNB Chain 3 Gwei
Polygon 42 Gwei
Arbitrum 0.5 Gwei
Optimism 0.3 Gwei

Market Cap

All →
1
Bitcoin
BTC
$76,050
1
Ethereum
ETH
$2,412.77
1
Solana
SOL
$97.61
1
BNB Chain
BNB
$713.2
1
XRP Ledger
XRP
$1.29
1
Dogecoin
DOGE
$0.0801
1
Cardano
ADA
$0.1947
1
Avalanche
AVAX
$7.29
1
Polkadot
DOT
$0.9592
1
Chainlink
LINK
$10.85

🐋 Whale Tracker

🔵
0x7017...0b00
6h ago
Stake
4,164,999 USDT
🔴
0x81a9...99c0
1h ago
Out
43,839 SOL
🔴
0x8ea0...674c
1h ago
Out
4,498 ETH

💡 Smart Money

0x5a4b...029b
Market Maker
+$4.9M
79%
0x6630...b6f1
Arbitrage Bot
+$0.9M
69%
0x9257...b7ad
Top DeFi Miner
+$2.3M
75%

🧮 Tools

All →
NFT

Partial Payments, Perfect Ambiguity: What XRP Ledger's Most Misunderstood Flag Teaches Us About Trust in Code

Leotoshi

There is a payment that succeeded, and yet delivered less than it promised, and nobody involved—not the sender, not the receiving exchange, not the protocol itself—was, strictly speaking, lying. I keep returning to that sentence because it captures something about blockchain that conventional audits miss entirely. The code computes. The ledger closes. The transaction is sealed into history. And somewhere deep in a settlement backend, an integer is read from the wrong field. Money evaporates. Not stolen in the cinematic sense, not drained by a reentrancy attack, not hacked through a stolen key. Just a flag enabled, a field misread, and a human assumption doing the damage that no vulnerability scanner will ever think to flag.

The feature is called Partial Payments, and it is native to the XRP Ledger, one of the oldest blockchains still running. Over the past decade, it has been called an exploit, a scam vector, a design flaw, and, more recently by its defenders, "not a bug." Every one of those labels contains a grain of truth, and that is exactly the problem. A label is not a protection. A payment type that can quietly mis-credit an exchange's balance sheet when read incorrectly is a payment type that will, sooner or later, be read incorrectly.

To understand why this matters, you first have to understand what the XRP Ledger actually is. It predates Ethereum, shares its ancestry with Bitcoin, and has spent most of its existence doing one thing with quiet determination: settling payments. There is no proof-of-work, no miner race, no public mempool. Instead, a federated consensus network of independent validators—selected through a Unique Node List, or UNL—approves and closes a new ledger state every three to five seconds. The result is transaction fees measured in fractions of a cent and settlement finality measured in seconds. For a chain built specifically for money movement, those are the only numbers that matter.

Beneath that surface simplicity lives real complexity. The ledger's native token, XRP, serves double duty as an anti-spam fee mechanism and, more importantly, as a bridge currency for cross-currency payments. The protocol supports path payments: you can send one form of value—say, USD-denominated tokens issued by one gateway—and have your counterparty receive a completely different form, such as EUR-denominated tokens from another issuer, with XRP as an intermediate hop. Liquidity along any single path is never guaranteed. A route might find 95 percent of what it needs and then run dry at the final step.

This is the engineering problem that Partial Payments was built to solve. The Payment transaction type carries an Amount field that states the intended delivery, and it can carry a flag, tfPartialPayment, that instructs the ledger to be pragmatic: if the exact amount cannot be delivered, deliver what can be delivered and still record the transaction as a success. In a network built on patchy liquidity and fragmented credit relationships, that flexibility is genuinely valuable. A transaction that settles at 90 percent can be reconciled later. A transaction that fails outright is a dead end for a merchant, a customer, and the reputation of the chain itself.

But the feature carries an uncomfortable asymmetry. The sender sets the intention. The protocol delivers a truncated reality. Hidden in the transaction metadata, a field named delivered_amount tells the truth about what actually arrived. And for more than a decade, the entire safety of this system has rested on the willingness of exchanges, wallets, and payment processors to read that one unobtrusive field instead of the far more visible Amount. As you might guess, many did not. Stellar's path payment operations share the same philosophical DNA; the difference is that XRPL's version has a long, documented history of being exploited, and that history is worth telling in full.

Let me walk through the mechanics in detail, because the devil lives in the flag. In a standard XRPL payment, the sender specifies an Amount, and the ledger sources the necessary funds from the sender's balance. Transfer fees may be deducted along the way, but absent those fees, the recipient receives exactly what the sender requested. If the required liquidity is unavailable, the transaction fails with a clear error. No ambiguity. No room for interpretation.

With tfPartialPayment enabled, the semantics shift. The ledger is authorized to deliver less than the stated Amount, and if it can source even a fraction—above whatever floor the sender has set—it will settle the transaction as a success. Modern versions of the protocol allow a sender to include a DeliverMin field, an explicit lower bound below which the deal should be declined rather than settled short. SendMax caps the maximum the sender is willing to spend, including costs along the path. The transaction result will display the familiar success code whether the delivery was full or partial. The single place where the difference becomes visible is the metadata.

And this is where the trap springs shut. For a partial payment, the transaction metadata contains delivered_amount, the actual value credited to the destination address. For a full settlement, delivered_amount and Amount typically coincide. The failure mode is baked into that asymmetry: a developer who builds deposit detection on the Amount field has created a system that handles full payments flawlessly and partial payments incorrectly—and will never notice until someone sends a partial payment with a very large stated amount.

The destination tag adds another layer of danger. XRPL exchanges use numeric destination tags to route incoming payments to individual customer accounts. An attacker can target a payment at a victim's destination tag, so the on-chain narrative reads as "a deposit for User 42" even if the delivered value is negligible. Reconciliation systems must not only read delivered_amount, but also confirm that the amount is consistent with an expected deposit; otherwise, the tag itself becomes an attack surface. And because path payments can swap currencies mid-flight, the received currency may differ from the requested one—a mismatch that frustrates automated crediting even when the numbers align. Each of these details is documented in the official literature. None of them is obvious to a first-time integrator.

A further nuance buried in protocol history: the delivered amount has not always been equally available for every transaction type. Early metadata sometimes required the observer to calculate the true delivery from the transaction path. The protocol eventually standardized delivered_amount precisely because the calculation was being performed incorrectly—or not at all—by the very integrations that needed it most. The standardization was an admission, in code, that the feature's ambiguity had become a liability.

I have stared at enough smart contracts to recognize the pattern. In 2018, I spent three months auditing the donation logic of a small DeFi prototype called EtherTrust. I found a reentrancy vulnerability that could have drained roughly two hundred thousand dollars from the project's treasury. That was a dramatic bug: a recursive call, an unchecked state update, a textbook exploit. But the failures that have shaped my view of this industry are rarely so theatrical. The money-eating errors usually live in the gap between what a transaction states and what it delivers, while the code executes flawlessly the whole time.

Consider the canonical attack. An attacker wants to deposit a large sum into an exchange without actually owning it. They construct a payment with Amount set to a thousand XRP, SendMax set to ten XRP, and the partial payment flag switched on. The ledger finds a path that delivers perhaps nine point five XRP. The transaction settles successfully. If the exchange's deposit handler is naive, it reads the Amount field, credits the attacker's account with a thousand XRP, and the attacker immediately withdraws the phantom difference—roughly ninety-nine times what they actually possessed. The ledger was honest. The exchange was sloppy. The attacker simply pointed the system at the wrong number.

This is not armchair theory. It happened, in waves, at real institutions, and it happened early in the network's life.

The partial payment attack is old enough to drink in most jurisdictions. In the early 2010s, when the network was still known simply as Ripple, exchanges and gateways wrote lightweight payment triggers: watch for inbound transactions, read the amount, credit the user. At that time, the ledger did not make the delivered amount unambiguously available in a separate, universally understood field. Attackers realized they could enable partial payment, deliver a pittance, and have that pittance treated as a fortune by the automated systems on the other side. A wave of thefts followed, targeting some of the first bridges between Bitcoin, XRP, and the banking world.

The industry's response was technical and, in retrospect, philosophically telling. The protocol introduced delivered_amount, a metadata field explicitly dedicated to the value actually transferred. It did not disable partial payments. It did not add a second confirmation step. It did not force exchanges to upgrade. It simply placed the truth inside the ledger and trusted that integrators would find it. This was the blockchain equivalent of installing a mirror at a blind intersection rather than rerouting the road—a decision to preserve the feature's flexibility while handing the cost of ambiguity to the people standing in traffic.

The resets kept coming anyway. Long after delivered_amount had been documented, tutorials written, and security alerts issued, the scam found new costumes. Fake payment screens circulated as phishing bait: a victim sees a fabricated confirmation window, complete with a large deposit and a green "successful" badge, while the actual blockchain transaction delivers a rounding error. In 2019 and 2020, security researchers and exchange operators found themselves issuing fresh warnings about partial payment tricks, probing the same weak points in new integrations. The advice never changed: read the delivered amount. Check the destination tag. Trust the metadata, not the message.

There is something almost tragic in this repetition. The vulnerability is not a secret. It is not a zero-day. It is not an unpatchable flaw. It is a known, documented, well-lit corner of protocol semantics that continues to catch newcomers. Why? Because the mental model most people bring to payments is that a successful transaction delivers what it says. On Bitcoin, that is true. On a standard Ethereum transfer, that is true. On the XRP Ledger, a successful transaction can deliver a fraction of its stated intent, and the only defense is knowledge. Decentralization does not hand out knowledge. It assumes it.

And here I must pause, because this pattern triggers something in me that has been building for years. During the DeFi Summer of 2020, I acted as a community liaison for a lending protocol and watched ordinary people deposit savings into platforms whose interfaces displayed yields that bore little resemblance to realized returns. The dashboards did not lie, exactly. They simply showed numbers designed for seduction and omitted the fine print that would have tempered expectations. When the market turned, the cry of "we never promised that" echoed through the wreckage. The code was fine. The incentives were fine. The humans were not.

The phrase "not a bug" works the same way. It is technically correct and morally incomplete. It describes the behavior of code while ignoring the behavior of people, and in doing so it becomes a shield held by the clever against the careless. The XRP Ledger's partial payments were never a bug. They have also, repeatedly, been a weapon. Both truths matter, and any honest analysis must hold them simultaneously.

Read in this light, the recent spate of "not a bug" explainers is less a technical contribution than a form of crisis communication. They are not proposing a feature; they are defending a reputation. Their audience is not the experienced validator set or the core protocol team, but the new user who has just seen a frightening headline, and the junior developer whose manager asked whether the XRP Ledger is safe to integrate. The answer is yes, with conditions—and those conditions are the entire story.

Let me steelman the "not a bug" position properly, because it deserves a fair hearing. Partial payments serve a legitimate function in path-based settlement. If a payment corridor from one institution-issued asset to another runs dry at 92 percent capacity, forcing the entire transfer to fail is wasteful and user-hostile. Partial delivery acknowledges that liquidity is a spectrum, not a binary. The flag is a pressure-relief valve for the messy reality of fragmented markets. Calling it a bug would be both wrong and reductive.

But the phrase still does damage, because it collapses a three-part claim into a one-word verdict. The three parts are: first, the feature is intentional; second, the feature has legitimate uses; third, the feature is safe when used correctly. The first two are plainly true. The third is true only for integrators who have done their homework—and the protocol has known for more than a decade that a meaningful fraction of integrators will never do that homework. When a design has a failure mode that is both well-documented and repeatedly exploited, insisting that it is "not a bug" is technically accurate and practically deceptive. It is the kind of statement that makes engineers feel precise while ordinary users pay the price of that precision.

There is a deeper ethical question here, and I think it is the question that keeps me writing about this industry. Every protocol encodes a distribution of responsibility. When the XRP Ledger introduced delivered_amount instead of disabling partial payments, it made a choice: preserve flexibility for sophisticated actors, and push the safety burden onto receivers. That is a defensible engineering decision. But it is not value-neutral. It creates a world in which the least sophisticated participants—small exchanges, new wallet developers, merchants integrating payment rails for the first time—are the ones who must learn the hardest lesson. The protocol stays elegant. The harm concentrates elsewhere.

In my audit work, I learned to look for the moment where code and expectation diverge. A reentrancy attack is a divergence. A slippage interface that hides price impact is a divergence. A payment flag that lets a transaction succeed while delivering less than promised is a divergence. The question that actually matters is never whether the divergence is intended, but who is expected to carry its cost. The XRP Ledger has answered that question clearly: the receiver carries it, forever, everywhere, unless they happen to know a magic field name.

So what does a responsible integration actually look like? The answer is deceptively simple, and its simplicity is exactly why it gets ignored.

First, never—under any circumstance—credit a deposit based solely on the Amount field of a Payment transaction. The authoritative value is delivered_amount in the transaction metadata. For older transactions and for every API response, ensure that the code path for partial payments and path payments reads this field and discards the comfortable assumption that the stated amount is the real amount.

Second, validate the destination. Confirm that the destination address and the destination tag belong to the user who is being credited. An attacker can send a partial payment with a victim's tag, creating a "successful deposit" record against a victim's account while delivering near zero. If the credit was not already triggered by reading the wrong field, the tag-spoof is the second door, and it swings just as easily.

Third, simulate. A testnet is not a marketing instrument; it is a failure-discovery tool. Build a harness that sends partial payments with tiny SendMax values, inflated Amount values, and varied path configurations, then watch what your backend does with the metadata. I am convinced that half of all integration bugs would be visible within a single afternoon of this exercise, and yet I have watched projects ship production payment processors without ever running it.

Fourth, communicate. The most common victims of partial payment confusion are not exchanges at all—they are end users who sent funds and saw a "successful" transaction that arrived lighter than expected. An interface that displays only "Payment Successful" without showing the received value is part of the problem. The delivered amount should be the headline number on any confirmation screen. The intent field belongs in an audit log, not in front of a customer.

What strikes me about this list is that none of it is complicated. It is the same discipline that applies to almost every dangerous feature in crypto: verification over assumption, explicit over implicit, and a healthy suspicion of any success message that does not show the real outcome. We already do this for token approvals. We do it for slippage. We do it for gas. On the XRP Ledger, we must do it one more time, for a field that has been sitting there all along.

The deeper lesson is about what "permissionless" actually means. A permissionless system does not guarantee safe integration; it guarantees possible integration. The difference is devastating. Anyone can connect to the XRP Ledger, but the protocol will not hold your hand, will not send a warning letter when you misread a field, and will not fail a transaction because the recipient's software is unsound. That is the price of freedom, and it falls disproportionately on people building for the first time. Seen from the perspective of the industry chain, the effect of all this education is quietly structural. Exchanges that internalize the lesson reduce customer disputes and accidental mis-crediting. Wallets that surface the delivered amount reduce support queries and build trust. Payment processors that simulate partial payment scenarios in testing avoid the kind of incident that ends partnerships. Traditional financial institutions exploring XRPL for cross-border settlement carry the lesson into rooms where blockchain's reputation is still being decided. A single flag, taught properly, becomes a small machinery of safety that propagates far beyond the ledger itself.

Stepping back, partial payments illuminates a tension that runs through every payment system, blockchain or otherwise: the distance between intent, execution, and confirmation. Traditional finance solved this with reconciliation departments—human teams that clean up the mess when systems disagree. Crypto, in its pursuit of automation, tried to solve it with cryptographic proof. But the proof only establishes what the ledger did, not what the integrator understood. The gap between those two realities is where all the ghosts live.

I have been thinking about this since 2026, when I began working with an AI-verification protocol called SynthVoice on a campaign we named "The Proof of Soul." The question was how to prove that a human created a piece of content in an age when machines can imitate anything. Our answer was cryptographic identity—signing one's humanity with a private key, making the authenticity claim verifiable on-chain. But the same lesson applies in reverse: a cryptographic proof is only as good as the discipline of the person checking it. A verified signature attached to a malicious payload is still malicious. A successful transaction that delivered half its promise is still half a theft.

This is why the "not a bug" debate is so instructive. It is not really about the XRP Ledger. It is about the recurring human fantasy that code can eliminate the need for care. The ledger does not care that you read the wrong field. The consensus system does not pause to ask whether the receiver understood what just happened. The transaction is immutable, and the loss is real, and the explanation—"actually, that's a feature"—is cold comfort to someone who just lost a deposit.

In that sense, the partial payment story is not merely a security anecdote. It is a case study in how decentralized systems distribute moral responsibility. The protocol cannot choose who reads its documentation. It cannot force exchanges to upgrade. It can only make the truth available and hope that truth finds its way to the people designing the interfaces, writing the deposit handlers, and setting the policies that determine whether a user loses money or keeps it. That is a fragile hope, and yet it is also the only hope that has ever worked.

The more I audit code, the more I believe that the decisive variable in a decentralized system is not the sophistication of its cryptography, but the clarity of its semantics. A protocol that says "successful" and means "partially successful" is not merely a protocol with an ambiguous flag. It is a protocol that has made a philosophical commitment to ambiguity—and asked the user to resolve that ambiguity with judgment the protocol itself did not provide.

Here is the uncomfortable turn. Maybe the partial payment debate has been framed wrong from the start. Perhaps the actual bug is our expectation that payments should be exact in the first place. Every payment rail on earth—bank wires, SWIFT, card networks—carries fees, floats, rounding, and clawbacks inside final settlement. "You sent one hundred, you received one hundred" is a retail convenience, not a law of nature. The XRP Ledger, with its partial payments and pathfinding, is brutally honest about this mess: liquidity is imperfect, paths are variable, and sometimes you receive less than you asked for. In that light, the flag is not a flaw. It is the only truthful feature in a hall of mirrors.

But hold that thought, because there is a second edge. If partial payments are the honest mirror, then the community's insistence on "not a bug" becomes something worse than protective—it becomes a form of gaslighting. When a feature has been weaponized against exchanges for over a decade, and when the only defense is a little-known field buried in metadata, responding to victims with "that's not a bug" is not intellectual rigor. It is deflection. The feature is a feature, and it is also a persistent, predictable source of harm. Both facts can be true at once, and any account that refuses to hold them together is doing propaganda, not engineering.

The fix, if there is one, is not to remove partial payments. It is to make the delivered amount impossible to miss—in the user interface, in the API response, in the documentation, in the warning systems of every downstream tool. Make ambiguity expensive. Make clarity the default. The protocol cannot force anyone to care, but it can stop pretending that reading the wrong field is an exotic mistake.

In an age when machines increasingly generate the messages we read and the transactions we trust, the XRP Ledger's partial payment story is a prophecy: the field you read is not the field you receive. The future will not be saved by cleverer cryptography, but by more honest semantics—by systems that make the delivered amount as visible as the promised one, and by integrators who treat the word "successful" as an invitation to verify rather than a conclusion. The ledger remembers what we prefer to forget. The question is whether we will learn to read it correctly before the next deposit goes missing. Trust is not a technology. It is a discipline.