Contributing to Writz
Writz is open source. Contributions - bug reports, code improvements, documentation, and security research - are welcome. This page explains how to contribute effectively.Ways to Contribute
Bug reports: If you find a bug in any of the contracts, circuits, relayer, or bitcoin-script toolkit, open a GitHub issue with a minimal reproduction. Include the test case if possible. Code contributions: See the open issues taggedgood first issue or help wanted on GitHub. All contributions require tests. The CI must pass before merge.
Documentation: Spotted something unclear, incorrect, or missing? Open a PR directly against the docs/ directory.
Security research: See the Bug Bounty page for responsible disclosure guidelines and rewards.
ZK ceremony participation: The Groth16 trusted setup ceremony requires independent participants. If you’re interested in participating, open an issue (writz.xyz has no mailbox yet). No technical background required - participants just need to run a script and discard their randomness.
Development Setup
Secrets
relayer/.env.example and frontend/.env.example are tracked deliberately, so
no .gitignore rule protects them, and a directory-wide git add stages
whatever they happen to contain.
A pre-commit hook scans staged additions for live-looking credentials, sk_
keys, Stellar S... seeds, Bitcoin WIF keys, PEM private key blocks and AWS
access key ids. Install it once per clone:
sk_... or sk_your_api_key_here do not trip it.
Two habits the hook does not replace:
- Review the staged diff, not the list of filenames. A file showing as modified when you did not expect to touch it is the signal worth stopping on.
- Treat a pushed secret as published. Deleting the commit does not un-publish it, and an orphaned commit stays reachable by its SHA. Revoke first.
Keeping the docs in sync
Contract addresses and test counts are quoted in a lot of places (README, SCF docs, community posts) and drift easily after a redeploy or when tests are added. Two scripts guard against that:- After a redeploy, update
contracts/deployments/testnet.md- it’s the source of truth every other doc is checked against. - After adding/removing tests, run
node scripts/update-test-counts.mjsto regeneratedocs/_data/facts.jsonfrom the real test suites. - Before opening a PR that touches deployments or docs, run
node scripts/check-docs-sync.mjs- it scans every.mdfile for contract addresses and “N tests” mentions that don’t match the current truth, and CI runs it on every PR regardless.
Code Standards
Rust / Soroban Contracts
- Run
cargo fmtandcargo clippybefore committing - Every public function must have a test
- Use
#[contractevent]for all events - no deprecatedEventsAPI - Per-entry persistent storage only - no growing
VecorMapin instance storage - Manage TTL: every write to persistent storage must set TTL thresholds
- No
unwrap()on user inputs - return errors viaResultor panic with descriptive messages
TypeScript (Relayer + Bitcoin Script)
- Run
bun run lintbefore committing - Every function must have a test covering the happy path and at least one error case
- No
anytypes - explicit type annotations required - Use the
Result<T, E>pattern for operations that can fail
Circom Circuits
- Every constraint must be intentional - document why it exists
- All public inputs must be explicitly marked
<== signal (public) - Test proof generation AND proof verification - not just compilation
- Test with both valid and invalid inputs - verify that invalid inputs are rejected
Pull Request Process
- Fork the repository and create a feature branch (
feature/your-feature) - Make your changes with tests
- Run
cargo test(contracts),bun test(bitcoin-script),bun run test(relayer),npm test(circuits) - all must pass - Open a PR with a clear description of what changed and why
- A maintainer will review within 5 business days
Open Items
The following areas are actively looking for contributors:
If you want to work on any of these, open an issue first to discuss the approach before writing code.