Skip to content

Styx Protocol · Changelog

Styx v2 changelog

Devnet onlyStyx v2 has run on Solana devnet since 2026-10-07. No real funds. Not externally audited. v1 stays on devnet as the fallback and will not go to mainnet.In English

Styx v2 has run on Solana devnet at styx.cash since 2026-10-07, 10:11 Paris time. Devnet only: test SOL, no real funds, no mainnet deployment. Not externally audited. v1 stays deployed on devnet as the fallback and will not go to mainnet.

Each line names the test or the devnet record behind it. Tests and records live in our repository, which has been private since 2026-10-02; the transactions are public on Solana devnet.

2026-10-18: the deposit fee in every view, Loofta's own page, the SDK package

In production on styx.cash since 2026-10-18, about 01:20 Paris (build d797f11c).

  • The deposit fee is counted wherever a deposit is planned. The light styx.cash tab that funds a partner balance now counts the pool's deposit fee: before, it counted a deposit at its face value and said 0.01935 SOL would stay when 0.01885 SOL did. The deposit fee notices of /app's Send now show; before, they never did. Backed by: web feeView.test.ts, PairPage.test.tsx and DepositFee.test.tsx (the fee view, the tab's line, the deposit size chosen after the fee, /app's send notice); found by our internal review of the release below (finding L1).
  • Loofta frames Styx from its own page only. The Styx frame for Loofta now opens only inside https://www.loofta.com, and its return link and claim page are on that origin; pay.loofta.com and loofta.com itself are refused (founder decision, 2026-10-18; loofta.com redirects to www.loofta.com). Loofta still has to host its claim page with the loader and allow styx.cash in its page's security rules. Backed by: web EmbedFrame.test.tsx, PairPage.test.tsx, sdkProtocol.test.ts and frameHeaders.test.ts.
  • The loader is a package. The loader is packaged as @styx-cash/sdk 2.1.0 and made ready for npm: a plain description, type definitions that name exactly what the loader exports and reads, and a README with the install line, the integrity hash of the loader styx.cash hosts and the rule on origins. Backed by: web sdkPackage.test.ts (the types match the loader, and the package's styx.js is the file styx.cash serves).

2026-10-18: the Styx frame inside a partner's card

In production on styx.cash since 2026-10-18, about 00:45 Paris (build 3cca14e2).

  • Inline in the partner's card. A partner site can show the Styx frame inside its own card, in a compact layout with one box of fixed height. In the light funding tab you choose the amount to put in; the tab uses one deposit at most and says what it adds beyond the payment. Loader 2.1.0. Backed by: web EmbedFrame.test.tsx, PairPage.test.tsx and sdkProtocol.test.ts.
  • The partner may change the amount before you send. The frame then drops the proof it made, shows the new amount, proves the payment again and keeps its confirm button off for a full second; a click while it is off is refused, and the frame says so. A proof made for another amount than the one asked never pays. Once the payment leaves, a change is ignored. Backed by: web EmbedFrame.test.tsx and sdkProtocol.test.ts.
  • A covered frame says so. When the browser reports the frame in view but covered for 2 s, the frame says "This page covers the Styx window, so it cannot pay here." and offers the same payment on styx.cash in a new tab, where Send opens filled in; the payment travels after the # only (a part of the address the browser never sends to a server), and the partner is told nothing. While a payment leaves, the frame shows no Cancel and no way out. Backed by: web EmbedFrame.test.tsx and AppV2.test.tsx; our internal review of 2026-10-17 (its surviving test mutants killed in 3cca14e2).

2026-10-17, about 22:20 Paris: a new device syncs in 37 requests

In production on styx.cash since 2026-10-17, about 22:20 Paris (build eb0f35a3, with our worker).

  • The initial sync reads ranges. A new device used to fetch the pool's public history one window (one block of that history) at a time: about 6,217 requests for the history as it stood on 2026-10-17 at 17:55Z. It now reads aligned ranges of 256 windows, then 16, then single windows: 37 requests for the same history. Every window of a range is checked as a single window is before the wallet uses it, and a range that fails its check is read again window by window. Every device that lacks the same windows asks for the same ranges. A device that comes back asks for the range that holds the first window it lacks: that tells where it stopped to within 256 or 16 windows, where single windows told it exactly. Backed by: pool-core mirrorRanges.test.ts; web v2MirrorForward.test.ts; the range run of 2026-10-17.
  • Measured, 2026-10-17. On a preview build of the site with our live worker, on the open internet, a fresh browser showed its balance 7.71 s after opening the app when the ranges were already held at the edge (the cache in front of our site), and 46.02 s when each range was asked for the first time (one run each). On one computer, with a local build of the site and a local worker, it took 8.2 s with ranges against 15.0 s with single windows, with no network delay. With the delays of our 2026-10-14 Tor run simulated, it took 19.0 to 25.8 s with ranges over 3 runs, while single windows were not done after 20 minutes. With the delays of a cold edge on the open internet simulated, 12.1 to 14.0 s against 296.3 s. The real Tor network has not been measured with ranges yet. Backed by: our internal review of 2026-10-17 (its preview run); the range run of 2026-10-17.

2026-10-17, about 17:15 Paris: the Styx SDK v2 for partner sites

In production on styx.cash since 2026-10-17, about 17:15 Paris (build dd684f6d).

  • A Styx frame on a partner's site. A partner site loads our loader, styx.cash/embed/v2/styx.js, and opens a Styx frame for one of three things: pay a payment link, claim one, or pay a Styx address or payment request. Only a partner listed in our configuration can frame its own page on styx.cash (/embed/ followed by its name); every other page of styx.cash refuses to be framed. A public Solana wallet is refused as a recipient, since paying one shows the amount and the receiver on chain. Backed by: web frameHeaders.test.ts, EmbedFrame.test.tsx and sdkProtocol.test.ts; the SDK check on devnet of 2026-10-17 (send, link, claim and sweep in one run).
  • The partner hears statuses only. The frame tells the partner site only where the action stands: ready, sent, claimed, cancelled, refused, failed or closed. The link, its secret, your words and your balance never reach the partner. Backed by: web sdkProtocol.test.ts and EmbedFrame.test.tsx (the messages through a payment, a claim, a funding and a pairing).
  • A balance for each partner site, made from your own words. The frame pays from a balance kept for that site and made from your 24 words: your words bring back every partner balance, and one partner balance's secret gives neither yours nor another site's. You set it up once in a light styx.cash tab: your wallet signs once, the tab pays the partner balance what it lacks, then closes itself. In /app, under Advanced, "Look for them" finds these balances from your words and moves what they hold into your own balance. Backed by: pool-core partnerBalance.test.ts; web PairPage.test.tsx and PartnerBalances.test.tsx; the SDK check on devnet of 2026-10-17.
  • A payment link lives 7 days past its maturity. After that, only the payer can take it back. Its expiry is rounded up to the hour, so the link tells its holder only the hour it was made (founder decision, 2026-10-17). Backed by: pool-core claimLifetime.test.ts.
  • The receiver claims on the partner's page first. The partner's claim frame also offers "Claim on styx.cash instead", which opens styx.cash in a new tab with the link's secret after the # only. Backed by: web EmbedFrame.test.tsx.

2026-10-17, about 02:00 Paris: checkpoints aimed at the end of the windows

In production since 2026-10-17, about 02:00 Paris (build 4f464ef4, our worker only).

  • A fresh deposit is less often pushed into the next window. A wallet sees a checkpoint (the row that makes a deposit spendable) only once the window that holds it is complete. Our worker now writes these rows 60 slots before the end of a window, instead of as soon as the program allows, so fewer deposits wait for one more window. In a model of the devnet settings, an estimate and not a measurement, the wait to the end of the window fell from a mean of 181.0 s to 123.4 s with a deposit every 30 to 300 slots, and from 147.8 s to 122.9 s when idle. No program, configuration or parameter changed. Backed by: pool-core crank.test.ts (never earlier than the program allows, a 20,000-input property) and litesvm gridCrank.test.ts on the real program (three deposits of one window go into one row); the crank model of 2026-10-15.
  • A wrong setting no longer stops the worker. A crank setting that is not a whole number now turns the aim off, with a line in the log, instead of stopping our worker. Backed by: pool-core crank.test.ts; found by our internal review of 2026-10-16.

2026-10-15, about 06:00 Paris: faster sends, fewer reads, a better restore

In production on styx.cash since 2026-10-15, about 06:00 Paris (build e781a4aa; our worker since 05:56 Paris). The speed figures compare 10 sends before and 10 after the release, from a headless browser on the open internet to devnet, 2026-10-15.

  • A funded send lands sooner. From the click to "Landed", a send from a funded private balance took a median of 9.01 s, against 10.25 s before (p90 10.16 s against 12.70 s). The app now looks for the landing every second, and our worker reports a payment's state as one more sealed read, padded like any other. Backed by: pool-core speed2.statusRoute.test.ts and speed2.statusLanding.test.ts; web Speed2Open.test.tsx; the speed runs before and after the release.
  • A failed send is seen in seconds. When our worker refuses a send, the app now sees it within about 1.2 s of the worker's answer, proves the payment again and sends it; before, it waited out a 120 s landing wait before trying again. Backed by: one forced failure on devnet on 2026-10-15 (a proof kept 570 s before the click, longer than the pool accepts: refused, proved again, landed 19.45 s after the click); the 120 s is the landing wait written in the wallet's code before the release (pool-core wallet/core.ts).
  • Far fewer reads when a page opens. A page made 43 to 46 sealed reads in the 4 minutes after it opened, against 510 to 531 before. Most of the old ones were a search of the v1 pools at every open; that search now runs only when you press "Look for my old v1 funds" in Advanced. Our site can see that a device searched, not what it found (founder decision, 2026-10-15). Backed by: web Speed2Open.test.tsx and AppV2.test.tsx (no v1 search at open; the button runs it once and says what it found); web pool v1OnDemand.test.ts; the speed runs before and after the release.
  • A failed read keeps your device's copy. A failed read no longer makes the device fetch the pool's whole history again: only a window (one block of that history) that the device's own check refuses is fetched again, and the whole history only when it truly disagrees with the chain. After the release, 7 pages never read the whole history a second time; before, that happened once in about 4.8 page-hours on the open internet, and under Tor it held one payment to 532.6 s from click to landing. Backed by: pool-core easy.test.ts ("a failed read keeps the kept windows"; "a check read behind the mirror is read again once"); the speed runs before and after the release; the Tor control run of 2026-10-15.
  • A restore from the 24 words brings back the wallet's own checks. After a restore, the checks before a withdrawal or a payment again see the wallets you deposited from and your past withdrawals. The wallets that funded your deposits cannot be recovered from the words, so the app asks you to confirm a withdrawal to any other wallet instead. Backed by: pool-core easy.test.ts ("the guard after a restore from the 24 words": the restored device gives the same warnings as the original one, and a withdrawal to a fresh wallet asks for a confirmation).
  • A payment link comes back from the 24 words. A link made from now on can be taken back with the 24 words alone once it expires unclaimed; to anyone without the words, its record looks like random padding. Links made before this release, or from a balance set up with a backup file, cannot. Backed by: pool-core easy.test.ts ("a link payment after a restore from the 24 words": taken back after its expiry, taken back only once, the record reads as filler).
  • The wait shown for a fresh deposit is closer to the real one. Since about 09:10 Paris the same day (build 12b48b24), the wait the app shows before a fresh deposit can be spent counts to the end of the window (one block of the pool's public history) that holds the next checkpoint, plus the page's fetch; it used to stop at the checkpoint itself. In the devnet test case, the app showed 116 s for a wait of 156 to 162 s on the timings measured that morning; it now shows 160 s. When the app does not know well enough where the windows start and end, it shows a range. Display only: no rule changed. Backed by: pool-core maturityDisplay.test.ts (the devnet case, the range, and the unchanged rule); commit 12b48b24 (116 s on the build before it); the speed run after the release of 2026-10-15.

2026-10-15: two routes for your IP address, and a lighter sync

In production on styx.cash since 2026-10-15 (build a4ced058).

  • Two routes for your IP address. Route 1 is the private route below: it is for everyone and needs nothing installed. Route 2 is Tor, optional, for people who already use Tor Browser; nobody is asked to use Tor. In Tor Browser the page still loads from styx.cash, through Tor. The app recognises Tor Browser by the name it announces (its user agent) and its UTC time zone, and confirms it only by reaching our .onion address (a server address that works only through Tor) within 15 s. It then sends every request to that address, sealed as on route 1: our onion gateway sees only Tor's own local address, and neither this site nor our worker sees your IP address. If the .onion address does not answer within 15 s, the app takes route 1 through Tor, and this site sees a Tor exit's address (the last Tor relay on the way), not yours. The gateway only serves the .onion address: it is not a Tor relay, an exit or a Tor client. Our worker does not use Tor to reach Helius, which sees no user's IP address on either route. Backed by: web torRoute.test.ts and TorOnionOnly.test.tsx; the gateway's torrc and nginx.conf; the real Tor network runs below.
  • Under Tor, nothing reaches this site's API. Before this fix, at the start of a page in Tor Browser, each payment sent 3 to 12 sealed reads to this site through Tor and kept trying to open a WebSocket (a long-lived connection) to it; both went through Tor, so this site saw a Tor exit, not you. Now the page starts on the .onion route and holds its reads until the .onion answers. Backed by: web TorOnionOnly.test.tsx (its routing cases fail on the code before the fix); the real Tor network runs of 2026-10-14 and 2026-10-15 (below).
  • A closed private balance stops its sync. When the app closes a private balance, its sync stops at the next window (one block of the pool's public history) and asks the chain nothing more; a page that went away before its balance opened opens none. Under Tor, the payer's device synced once, not twice, while its balance opened (3 payments, 2026-10-15). Backed by: pool-core easy.test.ts (after a close, at most the 8 windows already asked of 120, against all 120 before); web TorOnionOnly.test.tsx (a page that goes before its balance opened opens none).
  • The device keeps the pool's history without its padding. The copy of the pool's public history kept on your device now drops each window's padding of zero bytes and restores it exactly when read. Replaying 4,850 windows fetched from styx.cash on 2026-10-15, the copy held 3.2 MB of memory instead of 1,271 MB, and writes to the device's storage fell from 1,593 MB to 3.6 MB. A copy kept the older way is read as before and written again in the new form; nothing is fetched again. Backed by: pool-core easy.test.ts (a window comes back byte for byte; a balance whose device holds padded records opens, fetches only the 2 new windows and keeps its 1 SOL).
  • Measured on the real Tor network. In a Firefox that sent Tor Browser 15.0.25's user agent, not in Tor Browser itself. The .onion route was taken in 10 of 10 direct page loads and 9 of 10 through obfs4 bridges (unlisted entry points that disguise Tor traffic) on 2026-10-14, and in 6 of 6 loads on 2026-10-15. A page took a median of 2.7 s to load direct and 16.7 s through bridges (2026-10-14, 10 loads each). On 2026-10-15, 3 payments made 0 requests to this site's API, opened 0 WebSockets and sent 0 unsealed chain reads, and every payment landed. The initial sync of a new device took the payer 447.8 to 805.7 s; click to landing took 181.5 to 532.6 s. The slowest payment read the pool's whole history a second time after one failed read; since the release of about 06:00 Paris the same day, a failed read no longer does that (above). Backed by: the real Tor network runs of 2026-10-14 (production 7d6c0b78) and 2026-10-15 (production a4ced058).

What v2 adds over v1

  • Any amount. v1 moved fixed notes of 0.1, 1 or 10 SOL. v2 pays any amount up to 10 SOL from one private balance, filled by deposits in ten sizes from 0.005 to 5 SOL. Backed by: the pool settings written on devnet on 2026-10-04 (deployment record, section 5) and 30 payments of 0.12 SOL on 2026-10-05 (deployment record, section 8).
  • Your wallet does not sign your payments. Our relayer signs and pays each pool transaction, so a reader of the chain sees the relayer, not your wallet. Backed by: the fee payer of every measured pool transaction is the relayer key (launch log p03-pay-ohttp, 2026-10-07; WP10d transaction shapes, 2026-10-06).
  • A new verifier, checking every proof in full on chain. p01_stark_verifier_v2, deployed on devnet on 2026-10-04, checks each proof over the transactions our relayer submits: 60.7 per payment on average over 30 payments (2026-10-05). The hash is Poseidon2 with a four-element fingerprint, and the challenges come from a cubic extension field: the design answer to v1's findings F2 and F52. Backed by: the deployment record, sections 3 and 8; MAINNET-BUDGET, section 3.
  • Pay a Styx address. A static address you can share. A payment to it is sealed for you with post-quantum encryption, ML-KEM-768, combined with X25519; every record on chain has the same size and shape. Backed by: pool-core e2e.test.ts; web StyxAddress.test.tsx; a browser payment to a Styx address on 2026-10-07.
  • Payment requests and payment links. A request lets someone pay into your private balance, the amount set by you or by the payer. A link works like cash: whoever holds it claims it, with no wallet; the sender sees when. Backed by: pool-core wp10e.test.ts and claim.test.ts; one link paid and claimed on devnet on 2026-10-07 (deployment record, WP10e section E).
  • Clickable share links. A payment request, a Styx address or a payment link is shared as an https link to styx.cash/pay; the payment itself sits after the #, a part of the address the browser never sends to a server. Backed by: web payLink.test.ts, ShareLinks.test.tsx and PayLinkPage.test.tsx; a preview run on 2026-10-07, 14:22 to 14:32Z.
  • Withdraw to any Solana address, from 0.0016 SOL, on a 0.0001 SOL grid. Backed by: two browser payouts to fresh addresses on 2026-10-07, 23.3 s and 24.4 s from the click.
  • A private balance that opens by itself. Connecting asks for two signatures, one for your keys and one that unlocks the copy kept encrypted in your browser; neither sends a transaction or costs anything. The balance syncs in the background. You write down 24 words when the app reminds you, and those words alone restore it. Backed by: pool-core easy.test.ts and recoverable.test.ts (a words-only recovery, end to end); web PlugAndPlay.test.tsx; browser runs on 2026-10-07.
  • Sends leave at once. No send waits for a crowd. Below 20 people since your own deposits, the app says in one line that the receiver could match the payment by its time. Backed by: pool-core point82.test.ts; a browser payment from an empty private balance on 2026-10-07, 134 s from the click with no crowd.
  • The notice also covers the amount. When few people deposited at least the amount you send, the same line adds that the receiver could also find you by the amount, and gives their number. The send still leaves at once. Backed by: web FreeAmountSend.test.tsx (a small crowd adds the amount line, a large crowd shows neither line), 2026-10-07.
  • To my wallet. Send has a To my wallet button that fills the receiving address with the wallet you connected; the payment is then planned as your own withdrawal, with the guard below. Backed by: web FreeAmountSend.test.tsx (the button fills the address and the plan is an own withdrawal; no button without a connected wallet), 2026-10-07.
  • A payment link says its deadline. The claim page says how long is left to claim the link, and that claiming takes a few seconds. Backed by: web FreeAmountSend.test.tsx (the claim line is a deadline, in EN and FR), 2026-10-07.
  • Your own withdrawals keep their guard, for at most about 10 minutes. To the wallet you connected, a wallet you withdrew to before, or a wallet that funded your deposits: the app warns when the amount would match a payment you received and offers a different amount. If few others withdrew since you were paid, or few people deposited since your deposits, it waits for them, at most 8 to 12 minutes after the click (drawn at random), then sends anyway. Backed by: pool-core point82.test.ts, point84.test.ts, wp10f.test.ts, wp10e.exitShift.test.ts and wp10e.exitShift.wallet.test.ts; web OwnWithdrawal.test.tsx; the browser run of 2026-10-07.
  • Deposits go one at a time. Several deposits at once from one wallet would show the amount, so a wallet deposits one size at a time: within an hour of a deposit it waits, and a top-up that needs several sizes makes one now and the next ones 1 to 6 hours apart. A send that one deposit covers leaves after that deposit. Backed by: pool-core wp10f.wallet.test.ts and topup.test.ts; web FreeAmountTopUpRequest.test.tsx.
  • Your v1 notes move into v2. Held notes of the 0.1, 1 and 10 SOL pools count in your balance once found (since 2026-10-15, when you press "Look for my old v1 funds") and move into v2 when a send needs them. Backed by: pool-core migrate.test.ts; a migration on devnet on 2026-10-05 (deployment record, section 6d).
  • A private route for your IP address. On styx.cash this site relays your payment as a sealed message (Oblivious HTTP): it sees your IP address, not the payment; our worker sees the payment, not your IP address. Backed by: pool-core ohttp.test.ts; a payment through it on 2026-10-07, 32.5 s (launch log p03-pay-ohttp).
  • No IP address reaches Helius. The app reads the chain, sends your deposits and waits for your payments through this site; your browser opens no connection to Helius. Backed by: pool-core ohttpRead.test.ts and pollLogs.test.ts; web v2ReadRoute.test.ts and v2OhttpReadRelay.test.ts; two browser runs on 2026-10-07 with 0 requests from the page to Helius or another RPC host, one sealed through a local read gateway, one on a preview through the site's plain read proxy.
  • Sealed reads through our worker. Since 2026-10-07, about 18:25 Paris, our worker offers its read route: the app's reads and your wallet-signed deposits go sealed through this site to the worker, so this site sees your IP address and not what is read, and the worker sees what is read and not your IP address. If the route is unavailable, this site passes them on in clear and sees both, and the line before you send says so. Backed by: pool-core ohttpRead.test.ts; web v2OhttpReadRelay.test.ts; the internal attack test of 2026-10-07 (pass 3), whose live sample after the change counted 6 users, 0 requests to Helius or any other third party, 4,575 sealed reads and no plain read.
  • Sealed requests have one size. Every sealed request to our worker is padded before it is sealed to one size per kind: a submission to the submission size plus 1,024 bytes, a request that only asks for something to 512 bytes. This site, which relays them, can no longer tell a payment from a link or a withdrawal by its size. Backed by: pool-core ohttpPad.test.ts; in production since 2026-10-07, about 20:29 Paris. A live check that every sealed submission has one size is pending.
  • Every deposit has the same shape. Every deposit sets the app's own compute limit (310,000 units) and price (1,000 micro-lamports per unit, 310 lamports at the limit). A wallet extension that adds its own price only when none is set now leaves the same instructions and the same fee as any other wallet. Backed by: pool-core depositShape.test.ts and depositFee.test.ts; in production since 2026-10-07, about 20:17 Paris. A live check with a deposit signed by a real wallet extension is pending.
  • Abuse limits that cost no SOL. An anonymous proof of work on every submission, an on-chain reservation of the notes being spent, and a relayer budget with a stop-loss read from the chain. Backed by: pool-core pow.test.ts, budget.test.ts and precheck.test.ts, and the litesvm reserve.test.ts on the real programs; the adversarial runs on devnet of 2026-10-06 (deployment record, WP10c section C).

Fees and limits (devnet, set on 2026-10-04)

  • Deposit: 1 % of each deposit to the Styx treasury, plus the Solana fee of the deposit (0.000005 SOL, and 0.00000031 SOL for the fixed price since 2026-10-07) and 0.000000469 SOL to the pool's fee pot.
  • Payment or withdrawal: 0.00065 SOL from your private balance. The relayer pays the Solana fees.
  • At most 10 SOL per payment. Ten deposit sizes, 0.005 to 5 SOL.
  • A fresh deposit can be spent once the pool's next checkpoint includes it: one every 750 slots, 179 s at the devnet slot time measured on 2026-10-05 (238.4 ms).

Measured speed (devnet)

  • 30 payments from a funded balance through our hosted worker, 2026-10-06: median 20.0 s, p90 33.0 s, from the click to the landing. This was before the private route was on.
  • One payment through the private route, 2026-10-07: 32.5 s.
  • Two payouts to fresh Solana addresses, 2026-10-07: 23.3 s and 24.4 s.
  • One payment from an empty private balance, one deposit included, 2026-10-07: 134 s. It left 108 s after the click, once a checkpoint held its deposit. The receiver's app showed it 156 s after it landed.
  • 10 payments from a funded balance through the private route, 2026-10-15, after the release of about 06:00 Paris: median 9.01 s, p90 10.16 s, from the click to the landing.

What changed for v1 users

  • The app shows one private balance with Send and Receive. The Shield tab and the fixed amounts are gone.
  • Notes of the closed 100, 500 and 1,000 SOL pools cannot move into v2. The Advanced section keeps the recovery tools.
  • Subscriptions are parked for deeper work (2026-10-07): new subscriptions are not available, and since about 21:35 Paris the app hides the Subscriptions tab and says so in one line. The parking does not cancel v1 subscriptions already held (founder decision, 2026-10-07), but the app no longer lists them.
  • Nothing is lost on chain: a v1 deposit and a v1 withdrawal landed after the v2 upgrade (deployment record, sections 7 and 9d).

Internal attack test, pass 3 (2026-10-07)

Our own team, not an external auditor, attacked the live devnet traffic from 08:11Z to 17:47Z: 1,222 pool transactions, 159 deposits, 64 cases scored against what we knew to be true, from four viewpoints (receiver, sender, chain observer, our own operator) and with three independent attackers.

  • No structural link, no record link and no single party joining a payer and a payee was found, in any viewpoint. Each attacker named the right receiver for 0 of 44 senders.
  • The right names the attackers did find (19 of 172, 15 of 192 and 33 of 201 guesses) all came from the accepted residuals below or, from our own operator's viewpoint, from the tie through Helius that existed until 14:44Z, closed since (no IP address reaches Helius, above).
  • Accepted residuals, reported apart: a send right after the payer's own deposit can be matched by its time when few people deposited in between (founder decision, point 82); a payment of an amount that few depositors could cover can be matched by its amount (point 87); your own withdrawal can be matched by its time when few others withdraw, even after its wait of at most about 10 minutes (point 84).
  • Fixed after it: the deposit shape and the size of sealed requests (above). Their live checks are pending.

Known limits

  • Devnet only. Not externally audited.
  • Timing. Sends leave at once. When few people deposited since your deposit, a receiver who knows the amount and the minute could match your payment to your deposit by its time. The app says so before you send; v2 does not protect you against this in quiet periods.
  • On devnet, most of the crowd you hide in is our own test wallets.
  • The sender of a payment link sees when it is claimed.
  • Who sees your IP address: this site, when it relays a payment, a deposit or a chain read; it also sees what is read whenever the worker's read route is unavailable. Helius sees only our servers. Your wallet extension may contact its own servers when it shows you a transaction to sign. Styx runs both the site and the worker, so the private route splits what each server sees only while their logs are never joined; it does not hide you from Styx itself. In Tor Browser, route 2 keeps your IP address from this site and our worker (above); nobody is asked to use it.
  • Through Tor, the initial sync of a new device took minutes on 2026-10-15: 447.8 to 805.7 s for the payer in 3 payments, in a Firefox that sent Tor Browser's user agent. The ranges of 2026-10-17 (above) were measured with Tor's delays simulated on one computer, not yet on the real Tor network.
  • Tor Browser needs a Solana wallet extension installed in it: the app creates your keys from the extension's signature. Without one, the app cannot be used in Tor Browser.
  • Tor Browser at its default settings ("Always use private browsing mode" on) erases everything styx.cash stored in it when you quit it, including the encrypted copy of your private balance's secret; closing only the Styx tab keeps it; New Identity erases it. The app then opens a new, empty private balance, and your old one comes back only from its 24 words, with "Restore my private balance", before the new one holds any funds or requests. Keep your 24 words. If you switch that setting off, Tor Browser keeps styx.cash's data on disk across restarts, in a profile folder named after styx.cash, until New Identity or until you clear the site's data. Backed by: a test of Tor Browser 15.0.25 itself on 2026-10-17, on Linux in a test container (not on Windows), with clean quits; pool-core easy.ts (openPrivateBalance creates a new balance when nothing is stored).
  • Your own records are hidden under keys derived from your private balance's random secret. That hiding rests on the hash function: it is computational, not unconditional.
  • Amounts. When few depositors could cover the amount you send, the receiver could find you by the amount. The app says so before you send; the send still leaves at once.
  • Your own withdrawals. When few others withdraw, a withdrawal to your own wallet that leaves at its limit of about 10 minutes can still be matched by its time. A withdrawal split into standard parts can start up to 2 hours after the click.
  • In pass 3, every crowd except two wallets was ours (test wallets), so the cover that real users give each other is untested. Pass 2 saw link claims use 11 to 13 more compute units than payments on two samples; over 20 of each on the real programs the bands overlap (litesvm, 2026-10-07, pool-core wp10f.cu.test.ts), and pass 3 saw payments, links and claims in one band.
  • The values your wallet now writes into its own records, under one-time pads, need their own attack test before any mainnet launch.