No outside audit
The checks below are our own. No outside firm has audited the program or the circuits. Read Risks before you deposit.
What is tested#
| Layer | How | Result |
|---|---|---|
| Circuits | circomspect (Trail of Bits) on the four PoSL circuits; constraint tests with a cheating input per rule; a check that every verifying key in the program matches its proving key | 32/32; every circomspect warning checked by hand |
| Program | cargo test, cargo clippy, cargo audit; a randomized test over 200,000 epochs | 13 + 90 tests; 0 clippy errors; 0 vulnerable dependency |
| End to end | Local validator, real Groth16 proofs, a dishonest signer that rewrites instructions after the proof | 53/53 |
| Keeper | 11 missed epochs, one pass | 5/5 |
| Front | The full path in a real browser against the live local stack; passkey with a virtual authenticator; accessibility (axe-core) | 28/28; 0 accessibility violations |
Attacks that are refused#
| Attack | Refused by |
|---|---|
| A relayer swaps the recipient of a withdrawal | InvalidProof: the ext data hash binds the recipient |
| A relayer swaps the fee recipient | InvalidProof |
| A fake account in place of the pool vault | Anchor seed constraint |
| One byte of the proof changed | InvalidProof |
| A non-admin changes the parameters | Unauthorized |
| Opening an epoch out of order | WrongEpoch |
| Closing the current epoch | EpochNotOver |
| Locking beyond the longest lock, or until the current epoch | InvalidLockEpoch |
| A relayer fee above the maximum | RelayerFeeTooHigh |
| A volume claim of four empty credits | The circuit (reward must be above 0) |
| A self-relaying staker farming volume | Credit value = volume part of the fee (details) |
| Instructions placed before a claim to cut its logs | UnsafeTransaction: tree-changing instructions run at the top level, after compute-budget instructions only |
Findings fixed so far#
- Volume farming by a self-relaying staker (economic): fixed by the credit value rule.
- Empty volume claims made the relayer pay rent for nothing: fixed in the circuit.
- Keeper only looked at the last 8 epochs: it now catches up on any number.
- Admin fee rates could be raised to 100 %: now capped at 1 % in code and delayed (details).
- Sign-in message was fixed text a phishing site could ask for: it is now bound to the app domain (details).
TBD The full audit report of the current pass (severity, scenario, fix and test for each finding) is written to docs/AUDIT.md; this page will list it once merged.
Known limits#
- The four PoSL circuits use the keys of our own ceremony: three contributions, all from the team, so their safety rests on us having destroyed our randomness.
- The exit to Zcash lands on a transparent address first (a bridge limit).
- A young pool has a small anonymity set (Staying private).
- The relayer and the indexer can censor or delay, not steal (Privacy model). Anyone can run their own.
Report a problem#
If you find a way to lose, steal or freeze ZEC, or to link private actions, please report it privately to the team before telling anyone else. A public bug bounty comes later.