We Made the Chain Check Our Math: Zero-Trust Proration for Plan Changes
When a customer upgrades mid-cycle, someone calculates the credit for unused time — and everywhere else, you just trust that number. On Finality, the backend proposes the proration and the on-chain program recomputes it independently; if they disagree, the transaction fails. The story of why we put our own arithmetic in a cage.
The short answer: when a subscriber upgrades or downgrades mid-cycle, unused time on the old plan becomes a credit toward the new one — and somebody has to compute that number. In every billing system you've ever used, that somebody is the platform, and the number is whatever they say it is. On Finality, our backend proposes the proration and the on-chain program recomputes it independently from the committed terms; if the two disagree by anything, the transaction reverts. A miscalculation — or a manipulation — doesn't produce a wrong charge; it produces no charge. This is the story of why we built a system whose defining feature is that it refuses to trust us.
The most trusted number nobody checks
Proration is billing's fine print. Upgrade on day 19 of a 30-day cycle and a credit for 11 unused days should offset your first charge on the new plan. Every subscription platform does some version of this; almost nobody audits it. The number appears on an invoice, it looks plausible, life continues. The customer trusts the platform's code. The merchant trusts it too — it's their customer being charged, on their revenue, by arithmetic they've never seen.
That arrangement works fine — until the one day it doesn't, and on that day nobody can even tell. A rounding bug that always rounds one direction, a timezone edge that eats a day of credit, an off-by-one on cycle boundaries: these are quiet bugs, the kind that ship, run for months, and surface as a forum thread titled "am I crazy or was I overcharged?"
We were building subscriptions where the terms are welded into the vault's address precisely so nobody had to trust a database. It would have been strange to bolt onto that architecture a step where everyone trusts our spreadsheet.
What zero-trust means here, concretely
A plan change on Finality is one atomic transaction the customer signs once: the old vault closes, returning everything including the rent deposit, and the new vault opens with the credit applied. Inside that transaction:
- 1Our backend proposes the numbers — remaining time, credit amount, first-cycle offset — because something has to assemble the transaction, and that's a job, not a privilege.
- 2The on-chain program recomputes the proration from scratch, using only the old vault's committed terms and the chain's own clock — inputs nobody can quietly adjust.
- 3Any mismatch reverts the whole transaction. Not "logs a warning". Not "flags for review". The upgrade simply fails, everything stays exactly as it was, and the discrepancy is now loudly visible instead of quietly wrong.
The property this buys is easy to state and rare to have: our bugs are failures, not losses. If our proration code is wrong by one cent, no one gets charged the wrong amount — the transaction refuses to exist. The failure mode of dishonesty (or ordinary sloppiness) has been converted from "someone silently loses money" to "the operation visibly doesn't work", which is the correct failure mode for other people's money.
"But you could both be wrong"
The sharp objection: if the same team writes the backend and the on-chain program, couldn't the same bug live in both? Less likely than it sounds, for a structural reason: the two computations are written against different constraints, in different languages, running in different environments — one optimizing for orchestration, one for on-chain verification against committed terms. Correlated bugs are possible; quiet correlated bugs are much harder, because the on-chain side is public. Anyone — a merchant's auditor, a curious customer, a competitor hoping to embarrass us — can read the program and check the arithmetic themselves. Our math isn't just caged; it's caged in public.
That's the difference between "we double-check our work" (every serious company says this) and "the check is a public mechanism that blocks the transaction" (a property you can verify without asking us).
Why this matters beyond proration
Proration is small. The principle isn't. Billing disputes everywhere reduce to whose calculation wins — and the answer, everywhere, is "the platform's, and your recourse is support tickets". We wanted a system where that sentence has no referent: the platform can't hold funds, the keeper can't exceed terms, the merchant can't withhold commissions, and — closing the loop — the platform can't win an arithmetic dispute, because arithmetic disputes cause reverts, not charges.
Four posts into this series, the pattern has a name we keep arriving at from different directions: wherever a promise matters, remove the party you'd otherwise have to trust — even when that party is us. Especially then.
FAQ
Does the customer see any of this?
They see an upgrade that either completes exactly per terms or cleanly fails — no wrong charges to dispute later. The mechanism is invisible until you want to verify it, at which point it's fully public.
What happens operationally when a mismatch reverts?
Nothing changed on-chain — the old plan continues untouched. We investigate a loud, reproducible failure instead of hunting a silent discrepancy across months of invoices. Reverts are embarrassing and cheap; silent errors are invisible and expensive. We chose embarrassing.
Is this only for upgrades?
Plan changes in both directions — upgrades and downgrades — with credit flowing per the recomputed terms. The full subscription architecture covers the lifecycle around it.
How does a crypto subscription upgrade actually work here?
One customer-signed transaction: old vault closes (returning remainder and deposit), new vault opens with the credit applied — and the chain re-derives the credit before letting any of it happen.
How does proration work with crypto billing?
Same arithmetic as card billing — unused time becomes credit — with one difference: the platform's number is checked by the on-chain program, and a mismatch reverts instead of charging. Proration with crypto done this way is the only version the customer never has to audit.
Can I downgrade mid-cycle, or only upgrade?
Both directions — changing a subscription plan mid-cycle credits per the same recomputed terms whether the price goes up or down.
What if I'd rather just cancel and re-subscribe?
Always available — cancel returns everything including the deposit — but the migration flow does it in one signature with the credit math handled, so re-subscribing manually is strictly more work.
Does the customer pay for the recomputation?
It runs inside the migration transaction's normal execution — no extra fee, no "plan change charge". Billing events that bill you for happening are a card-world habit we declined to import.
Most billing systems ask for your trust; this one submits its homework for grading, every time, in public. Run a plan change in the sandbox and watch the one transaction do all of it — close, credit, reopen — or refuse entirely. Those are the only two outcomes it knows.