Skip to main content

CoinDesk ran a short piece on 19 October 2026 under a headline that reads like a joke the XRP Ledger is telling on itself: XRP Ledger is set to fix its lending code before anyone can use it. A package of bug fixes called fixCleanup3_4_0 has the validator support it needs and activates around 09:34 UTC on Friday 23 October. Some of those fixes repair Ripple’s uncollateralised lending system. That system is nineteen votes into a twenty-nine vote requirement and has not started its two week countdown, so it cannot be switched on before November at the earliest.

That is a good story and it is correctly reported. It is also the half everybody is asking about. The question is whether the fix passes and what it fixes. Nobody has asked what else is on the same ballot paper.

I went and counted. fixCleanup3_4_0 is not a lending patch with some tidying attached. It gates fifty-eight separate runtime behaviour changes across thirty-four source files, and ten of those fifty-eight are in lending code. Thirty-seven of them sit in subsystems that are live on mainnet right now, carrying real money: payments, the order book, the AMM, escrow, NFT offers, token freezes and the signature check that runs on every transaction the network accepts.

Twenty-nine validators voted yes to all of it with one bit each.

TL;DR

  • fixCleanup3_4_0 activates at approximately 09:34:30 UTC on Friday 23 October 2026. I confirmed it by reading the Amendments object on ledger 107,758,098 directly: it is the only entry in Majorities, with a close time of 9 October 2026 09:34:30 UTC and a fourteen day timer.
  • Measured against the rippled 3.4.1 tag, the amendment gates 58 runtime checks in 34 non-test source files, with 42 further references and 38 test files. Only 10 of the 58 are in lending code.
  • 37 of the 58 change the behaviour of subsystems already enabled on mainnet, including Payment, OfferCreate, OfferStream, four AMM transactors, NFT offer validation, escrow, checks and the transaction signature cache.
  • The public API changelog names exactly one of those fifty-eight behaviours. The amendment itself is named after a release number, which tells a voter nothing.
  • 11 of the 29 validators backing the fix have not voted for LendingProtocolV1_1, the feature it partly repairs. Nine of them have voted for neither lending nor the vaults.
  • Satoshie draws from a Chainlink VRF 2.5 coordinator on Base whose only economic setter, setConfig, takes nine parameters at once and has no single-parameter alternative. We get no vote on it at all, and neither do our players.

The hundredth unasked half of fairness

This series has spent ninety-nine instalments on the same move: take the question everyone is asking about a piece of crypto infrastructure, find the question sitting directly underneath it that nobody is asking, and check whether the second one has an answer. The hundredth is about a ballot.

Amendment voting on the XRP Ledger is, genuinely, the most disciplined upgrade process in this industry. Every rule change is gated behind a named flag. Every gate is permanent and readable in public source. A change needs more than eighty per cent of the trusted validator set, and that support has to hold for two straight weeks before anything moves. Compare that to a chain where a core team ships a release and the rules change when enough people restart their nodes.

And the unit on the ballot is a release, not a change. That is the hundredth unasked half: THE BALLOT NOBODY SPLIT.

What is actually on the paper

I cloned the rippled repository at tag 3.4.1, the release currently being voted on, and counted the places where the code asks whether this amendment is enabled.

Measurement (rippled tag 3.4.1, non-test code) Count
Runtime checks of the form rules().enabled(fixCleanup3_4_0) 58
Source files containing at least one such check 34
Further references (comments, flag slots, era notes) 42
Total references in non-test code 100
Test files that reference the amendment 38
Runtime checks inside lending code 10
Runtime checks inside subsystems already live on mainnet 37
Runtime checks inside dormant subsystems (vaults, lending, sponsorship) 21

Group the fifty-eight by where they live and the shape of the thing becomes obvious. Nineteen files of transactors hold forty-eight of the hundred references. Six invariant files hold nineteen. Eight ledger helper files hold eighteen. The rest are spread across the payment engine’s view layer, the signing code, the peer overlay and the server’s network operations module.

Put plainly: a validator operator who wants the lending default rules corrected is also voting to change how a payment with a domain identifier is validated, when an offer gets thrown out of a permissioned order book, which bytes a sponsor signature covers, and whether an NFT offer can be denominated in a fake currency called XRP. There is no mechanism on the XRP Ledger to accept some of those and refuse the others. There never has been.

Four changes nobody voted on separately

These are not hypothetical. I read them in the 3.4.1 source.

Payments can no longer mint on a burn permission. In Payment.cpp, an account holding only the granular PaymentBurn permission could, before this fix, redeem past the balance it actually held. The payment engine crosses zero at that point and starts issuing the issuer’s own IOUs, which is a mint rather than a burn. The gated code now compares the amount against the balance held. This is the loophole the 3.4.0 release notes describe, and it is the one piece of the amendment that has had any press.

Permissioned payments now read the domain and clean up after it. Two further gates in the same file make a payment carrying a DomainID read the permissioned domain object, return tecNO_PERMISSION if it is missing, and delete expired credential entries from the ledger during application. Credentials and permissioned domains are both live features today.

The order book got a new fatal error. In OfferStream.cpp, an offer indexed in a domain book that does not itself claim that domain now throws tecINTERNAL. The comment in the source is admirably blunt about why: without it, such an offer “would otherwise be consumed from a domain book without any credential check”. That is the live decentralised exchange, not a dormant feature.

Signature verdicts got a second cache. In apply.cpp, signatures in the counterparty and sponsor role fields now cover different prefixes from the transaction’s own signature, so a signature can no longer be lifted from one role into another. Because the node caches signature verdicts by transaction hash, the fix also adds two extra flag slots so that a verdict reached under the old prefixes is never reused under the new ones. That is a change to the code path that validates every transaction on the network.

And a fifth, because it is the one that shows how wide the net is: in NFTokenHelpers.cpp, an NFT offer denominated in a non-native currency whose three letter code happens to be XRP is now rejected as temBAD_CURRENCY, and an IOU issuer is exempted from their own global freeze when the offer is denominated in their own IOU. Two unrelated rules in the live NFT marketplace, riding on the lending patch.

The documentation names one of fifty-eight

The rippled repository keeps an API-CHANGELOG.md, and the section for 3.4.0 is thorough. Thirteen bullets describe behaviour changes in that release. Exactly one of them names fixCleanup3_4_0: the signature prefix change, with the new four character prefixes CPT, CPM, SPN and SPM spelled out for client developers. The other twelve are ordinary API changes that are not amendment-gated at all.

That is not negligence. An API changelog documents what breaks clients, and most of fifty-eight consensus rule changes do not break clients. But it means the only itemised public record of what this amendment does covers one fifty-eighth of it, and the release notes add a handful more in prose. Everything else is discoverable only by reading the diff, and the diff is not what is on the ballot. The ballot is a name.

The name is the other half of the problem. fixCleanup3_4_0 is named after the release it shipped in. So is fixCleanup3_3_0, and fixCleanup3_2_0, and fixCleanup3_1_3. Compare that to the ledger’s older amendments, which are named after what they do: fixNFTokenNegOffer, fixXChainRewardRounding, EnforceInvariants. Those names are a specification. A version number is a date.

And the bundles are not small. Counted the same way in the same tree:

Amendment Non-test references Files Status
fixCleanup3_1_3 34 16 Enabled
fixCleanup3_2_0 82 40 Enabled
fixCleanup3_3_0 34 20 Enabled
fixCleanup3_4_0 100 39 Activates 23 October

A fifth, fixCleanup3_5_0, already exists in the development branch waiting for its release. This is now the normal way the XRP Ledger changes its rules.

Eleven validators are fixing code they will not switch on

Here is where the single bit becomes visible in the voting data rather than the source.

I pulled the voter list for three amendments and checked every address against the published default validator list at vl.ripple.com, sequence 85, which carries thirty-five validators. Every voter on all three is in that list.

Amendment Votes Needed Countdown
fixCleanup3_4_0 29 29 Started 9 October, ends 23 October
SingleAssetVault (XLS-65) 21 29 Not started
LendingProtocol (XLS-66) 19 29 Not started
LendingProtocolV1_1 19 29 Not started

Twenty-nine of thirty-five is 82.9%, and twenty-eight would be exactly 80%, which is not more than 80%. The fix has no votes to spare. One validator withdrawing support restarts the two week clock.

Now intersect the lists. Eleven of the twenty-nine validators backing fixCleanup3_4_0 have not voted for LendingProtocolV1_1: aureusox.com, ekiserrepe.es, katczynski.net, onxrp.com, tequ.dev, v2.xrpl-commons.org, validator.aspired.nz, www.bitrue.com, xrp-validator.interledger.org, xrp.vet and xrpgoat.com. Nine of those eleven have voted for neither lending nor the vaults that would hold the lenders’ money.

Read that carefully, because it is not an accusation. Those eleven are not being inconsistent. They are doing the only thing the ballot allows: voting yes to a package whose non-lending contents they want, while declining to enable the lending system itself. The fix to the lending code sails through on the votes of operators who have no intention of letting lending run. The lending code gets corrected by people voting against lending.

That is a perfectly rational outcome of a ballot with one box. It is also not what “validators approved the lending fix” sounds like.

Two dashboards, two tallies, one ledger

A smaller finding, recorded because this series keeps running into it. The XRPL Dashboard, which CoinDesk cites, reports 29 votes against a threshold of 29 out of 35. The XRPScan API reports a count of 26 against a threshold of 25 out of 32. Both are looking at the same amendment on the same day.

Neither is wrong. The denominator differs: thirty-five is the size of the published trusted list, thirty-two is the number of those validators currently producing validations. The voter arrays agree exactly at twenty-nine, and all twenty-nine are in the published list. Three validators in the trusted set are quiet, which moves both the count and the threshold down by three.

The thing that settles it is neither dashboard. I asked a public rippled node for the Amendments ledger object at validated ledger 107,758,098 and read the Majorities array. It has exactly one entry: amendment 98433DD0…, close time 844,853,670 in Ripple epoch seconds, which is 9 October 2026 at 09:34:30 UTC. Ninety-seven amendments are enabled; this one is not, yet. The ledger has already made the decision the dashboards are reporting on, and it will say so in its own state on Friday.

Sixteen amendments are waiting. The bundle is the only one moving.

Sixteen amendments are pending on the XRP Ledger right now. Eleven are features, five are fixes, and ninety-seven others are already enabled. Exactly one of the sixteen has a countdown running, and it is the bundle.

The rest of the queue is a record of how hard it is to get a single-purpose change through. LendingProtocol has been on the ballot since release 3.1.0 on 28 January 2026, close to nine months, and sits at nineteen. XChainBridge arrived with 2.0.0 in January 2024 and has four votes. PermissionDelegation has one. Four amendments have none at all: fixNFTokenNegOffer and fixNFTokenDirV1 from the 1.9.2 and 1.9.1 releases in 2022, NonFungibleTokensV1 from 1.9.0, and CryptoConditionsSuite, which has been waiting since 0.60.0. Three of those four are bug fixes, and they have sat at zero supporters for more than four years.

Set that against fixCleanup3_4_0, released on 17 September 2026 and at a full majority within three weeks. On the evidence of this queue, the fastest way to change a rule on the XRP Ledger is to put it in a package with fifty-seven others.

One more detail from the source, because it cuts the other way and belongs here. Every amendment carries a default vote in features.macro, which is what a validator supports when its operator has configured nothing. fixCleanup3_1_3 is DefaultYes. fixCleanup3_2_0, fixCleanup3_3_0 and fixCleanup3_4_0 are all DefaultNo. The twenty-nine yes votes are twenty-nine deliberate acts, not a default quietly carrying a package over the line. That is to the operators’ credit, and it sharpens the question rather than settling it: twenty-nine people chose this, and this was the only unit on offer.

Why bundling is not a bug

It would be cheap to finish here and call this a governance failure. It is not one, and the reason is worth stating properly.

Every amendment a chain supports independently doubles the number of rule combinations its software must be able to execute. Fifty-eight separately votable switches would mean the network has to be able to replay history under any of 258 rule sets, and every one of those combinations is a path through the code that somebody has to reason about and test. Bundling is how you keep the combinatorial surface finite. The XRP Ledger already carries ninety-seven enabled amendments; nobody wants nine hundred.

Nor are validator operators blind. The gates are in public source, extensively commented, and the people running these servers are not amateurs. “Nobody split the ballot” does not mean nobody could read the diff. It means no itemisation was ever on the ballot, so the reading is optional, unverifiable from outside, and leaves no record. You cannot tell, from the chain, whether a validator read fifty-eight changes or one headline.

The honest version of the criticism is narrower and harder to dismiss: the governance mechanism is excellent and the ballot design wastes it. Two weeks of cooling-off on a question nobody can answer partially is two weeks of cooling-off on a yes or no to a version number.

Where this lands on a draw

Satoshie runs raffles and coinflips on Base, with randomness from the Chainlink VRF 2.5 coordinator at 0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634. The temptation is to say we are better placed than XRPL here. We are not. We are worse, and the comparison is instructive.

The coordinator’s economics live in one function. setConfig takes nine parameters: minimum request confirmations, maximum callback gas, the staleness window, gas after payment calculation, the fallback LINK price, two flat fee fields and two premium percentages. There is no setter for any one of them. Changing the staleness window means re-supplying the premium, the fee and the gas ceiling in the same call, and the ConfigSet event emits all nine whether eight of them moved or not. One transaction, nine knobs, no partial acceptance. It is the same shape as fixCleanup3_4_0, at one fourteenth the size.

A previous instalment measured what that function will accept and who can call it. The point here is different and simpler: there is no ballot. Nobody votes on a setConfig call. No fourteen day countdown runs. No threshold has to be met. The contract owner sends a transaction and the economics of every draw on Base change in one block, which another instalment found that fifty-seven of fifty-nine game contracts on the chain cannot escape, because they can be pointed at a different oracle by their own owners.

Base itself is no different. A hard fork activates when a timestamp in the chain configuration passes and the nodes that implement it carry on. There is no supermajority, no cooling period, and no object in the chain’s own state recording that a decision was made, which is the same shape as a constant that moved on another chain and shortened an epoch by six hours without anyone voting on it. The XRP Ledger at least writes its pending decision into a ledger object you can read, which is how I checked Friday’s date rather than taking a dashboard’s word for it.

And our players get the least of anyone. When Satoshie changes a contract, the ballot has one voter. We publish, we leave the proofs verifiable, and a draw stays checkable against the randomness that produced it. What we do not have, and have never claimed to have, is twenty-nine independent operators who would have to agree before the rules of the game could move.

Honest limits

This is not an XRPL defect. Gating every rule change behind a named, permanent, publicly readable flag is better engineering than most of this industry manages. The criticism is of ballot granularity, not of the amendment system, and the amendment system is why the measurement in this post was possible at all.

Bundling has a real reason. The combinatorial argument above is not a fig leaf. Independent switches multiply the rule sets a node must support, and that cost is paid in bugs.

A reference is not a user-visible change. I counted fifty-eight runtime checks. Some of them are defensive, including the OfferStream throw, which should never fire on a healthy ledger. The number measures how widely the amendment reaches into the code, not how many behaviours an ordinary account will notice.

My counts come from one tag. Everything here is measured against rippled 3.4.1. A different tag would give slightly different numbers, and the amendment’s contents were frozen when 3.4.0 shipped on 17 September 2026, so the gates cannot change now, but the surrounding code can.

We have no vote and neither do you. Every criticism in this post applies more sharply to Satoshie than to the XRP Ledger. A single owner key reconfiguring an oracle is not an improvement on twenty-nine operators agreeing on a bundle. It is the same problem with the quorum removed.

Three questions

For a validator operator: when you voted yes to fixCleanup3_4_0, how many of the fifty-eight did you read, and is there anything in the chain’s state that would let anyone else find out?

For anyone building on a permissioned order book or an NFT marketplace on XRPL: your rules change on Friday morning. Did you know that from the amendment’s name?

For us: if a ballot with one box is a weak form of consent, what exactly is a payout whose terms can be changed by one signature, and what would it take to put a countdown on that?

The closer

Provable fairness is a claim about a single draw: this number was uniform, nobody chose it, here is the proof. Every instalment of this series has eventually found the same boundary, which is that a proof about a draw says nothing about the rules the draw ran under, or about who got to change them.

On Friday morning the XRP Ledger will change fifty-eight of its rules at once, correctly, transparently, with two weeks’ notice and the agreement of twenty-nine independent operators, and almost nobody will be able to say which fifty-eight. That is not the worst version of this problem. It is the best version, and it is still a ballot with one box.

We draw winners with verifiable randomness and we publish what we measure, including the parts where we come off worse than the thing we are writing about. If you want to see what a draw looks like when the proof is the product rather than the marketing, that is Satoshie.

Sources: CoinDesk, 19 October 2026. The XRP Ledger Amendments object at validated ledger 107,758,098 via a public rippled node. The rippled repository at tag 3.4.1. The XRPScan amendments API and the default validator list at vl.ripple.com, sequence 85. The Chainlink VRF 2.5 coordinator source on Base.

📷 Photo by mostafa mahmoudi on Unsplash

Valentina Ní Críonna

Author Valentina Ní Críonna

More posts by Valentina Ní Críonna