Known limits
Every known limit of Tally, stated plainly: testnet only, unaudited, built on an untagged preview branch, a seven-day verification window, no users, and what the planned operator design cannot avoid.
This page lists what Tally does not do, does not have, or cannot yet guarantee. Each item links to the file it comes from.
Testnet only. No users, no integrations. Nothing has been audited. Do not use with real value.
Status
| Limit | What it means | Source |
|---|---|---|
| Testnet only | Everything runs on Stellar testnet. Nothing is deployed on mainnet. Testnet XLM has no value | README; evidence README |
| Unaudited | Nothing in Tally has been audited. The OpenZeppelin confidential-token suite it builds on is an unaudited developer preview | README |
| Built on a preview branch | Tally pins OpenZeppelin stellar-contracts v0.9.0 (df602b6). v0.9.0 is a branch, not a tagged release. OpenZeppelin's main and v0.9.0 have diverged, and which one mainnet will use is an open question | README; OPERATOR-DESIGN §9 |
| No users or integrations | Tally has no users, no integrations and no partner agreements. Nothing in the repository is used by anyone else | DEMONSTRATION-STATUS |
| No independent verification yet | Nobody outside the project has run the verifier on a published round and reported the output | DEMONSTRATION-STATUS, row 8 |
| Demo recipients are not people | The published round was generated by a test harness. Its recipients are freshly created testnet accounts. A round with real, independent contributors holding their own keys has not been built | evidence README; DEMONSTRATION-STATUS, row 9 |
| SDK is internal and unaudited | The client SDK under ct/sdk is Tally's own port of the reference demo's SDK to v0.9.0. It passes the 19 OpenZeppelin v0.9.0 primitive vectors it implements. It is not published as a package and not audited | DEMONSTRATION-STATUS, notes |
What the guarantee does not cover
The trust statement is scoped on purpose. Two limits follow directly from its second sentence.
| Limit | What it means | Source |
|---|---|---|
| Only the declared lanes | The proof covers transfers from the lane accounts declared before the round, within its ledger window. It says nothing about the funder's other accounts or total spend | TRUST-STATEMENT |
| Recipient independence is not verified | A funder can pay accounts it controls and prove a valid total. The proof shows what amounts moved, not who controls the receiving accounts. A recipient-identity layer is future work and outside the current scope | TRUST-STATEMENT; README roadmap |
| Repeated aggregates | Aggregates over overlapping sets of transfers could be subtracted from each other to narrow down amounts. Checks against this are not designed yet | OPERATOR-DESIGN §7, T13 |
Verification window
| Limit | What it means | Source |
|---|---|---|
| About 7 days of events | Soroban RPC keeps a rolling window of events, about 120,960 ledgers or roughly 7 days on testnet. The verifier lists a round's transfers from chain events on purpose, so after the window it has nothing to list | SDK-SAFETY-INVARIANTS §I4 |
| No durable archive | Every published round stops being verifiable when its ledgers leave the window. tally verify detects this and exits with code 3. pnpm evidence:refresh publishes a fresh round, which keeps current evidence checkable but does not make an old round checkable. A durable path (event archive or ledger replay) is designed and not built | evidence README; DEMONSTRATION-STATUS, row 11 |
| Earlier rounds cannot be reproduced | round-001 and round-002 (August 2026) came from the retired deployment. Their ledgers have left the window and their pinned verification keys no longer match the current circuits | evidence README |
| Explorer view is from the retired deployment | The decoded explorer view of a transfer was made against the August deployment and has not been regenerated against v0.9.0 | DEMONSTRATION-STATUS, row 2 |
The payout flow
| Limit | What it means | Source |
|---|---|---|
| One transfer per transaction in the demo | Four confidential transfers from one sender fit in one transaction, and this was demonstrated on testnet through a measurement-only wrapper. The demo still sends one transfer per transaction. Moving the payout flow to batching is unscheduled | MEASUREMENTS; DEMONSTRATION-STATUS, notes |
| No browser registration page | Non-custodial registration works headless and is tested against live testnet. There is no wallet connect page | DEMONSTRATION-STATUS, row 5; registration README |
| Demo lane keys in plaintext | The demo writes the funder's lane spending keys in plaintext to demo/last-round.json. The file is gitignored and holds testnet keys only. A real funder would hold them in a signer service | cli README |
| Override still present in the SDK | Safety invariant I1 says the transfer path must not expose an override for the ephemeral scalar. The ported SDK's transfer witness builder still accepts an optional rE. It defaults to the derived value | SDK-SAFETY-INVARIANTS §I1; ct/sdk/src/witness/transfer.ts |
| Measured on one machine | Proof generation times were measured on an Apple M4 Pro. Other hardware will differ | MEASUREMENTS |
The planned operator service
The operator service (split auditor-key custody, scoped audit requests, disclosure outputs, list management, tax export) is designed, not built.
| Limit | What it means | Source |
|---|---|---|
| None of it exists | Auditor-key custody, scoped audits and list management are a design only | DEMONSTRATION-STATUS, row 12; OPERATOR-DESIGN §6 |
| The design's weakest point | OpenZeppelin's clawback proof and auditor-side disclosure proofs need the whole auditor key as a private witness. The design reassembles the key briefly inside an attested enclave (TEE) to produce those proofs, so for the duration of one proof the key exists in one place. A hardware-level attack on the enclave would expose it | OPERATOR-DESIGN §2.3, T5 |
| Colluding custodians | If t custodians collude, they can decrypt every account bound to that auditor. Cryptography cannot detect this; deterrence is contractual | OPERATOR-DESIGN §7, T1 |
| Commercial custody is unverified | Whether commercial MPC custody products support the curves these systems use is unverified and thought unlikely | OPERATOR-DESIGN §2.2 |
| Mainnet depends on others | Mainnet work follows SDF's approval of Confidential Tokens for mainnet. Its timing is outside the project's control | SCOPE-LEDGER |
| SPP lists cannot remove members | In Nethermind's Stellar Private Payments the allowlist has no delete. A blocked subject who makes fresh note keys outside the admission flow is not caught by a blocklist-only pool | OPERATOR-DESIGN §5 |
Demand evidence
The written evidence that anyone wants this operator is one explicit ask, at one SDF meeting. On 2026-08-06 the official meeting notes, written by SDF DevRel, say "Nobody is building that platform for you. Hint." and record SDF's privacy product manager's ask, in paraphrase, to "go be the operator". Other claimed asks on video could not be confirmed from captions. No statement by SDF, OpenZeppelin or Nethermind says they will not build this themselves (OPERATOR-DESIGN §0; DEMAND-QUOTES).
Secret guard
What scripts/check-secrets.ts detects, how the allowlist works, how the retired demo key is matched by hash, the negative tests, and how CI runs the guard before anything else.
Operator design
Split auditor-key custody, scoped audit requests, disclosure outputs and allow/deny lists. Designed, not built.