Thank you for considering a contribution to FlowFi. This document covers everything you need to know to go from "interested" to "merged PR."
- Project Philosophy
- Code of Conduct
- How to Find Something to Work On
- Local Environment Setup
- Running Tests
- Code Standards
- Branching Strategy
- Pull Request Guidelines
- Issue Labels
- Design Discussions
- Onboarding Path for New Contributors
FlowFi is built on three principles:
1. Openness over completeness. We prefer shipping a working but incomplete protocol and inviting contributors to build it out, rather than building everything behind closed doors and open-sourcing a finished product. This means the codebase is intentionally incomplete in well-labeled places.
2. Education as a feature. Every TODO, every comment, every architectural decision should be legible to someone learning Soroban. Code that is clever but opaque is a bug. Code that is slightly verbose but clearly explained is preferred.
3. Protocol correctness over gas optimization. This is not an Ethereum mainnet protocol. Soroban fees are low. We will not sacrifice safety or clarity for micro-optimizations. When in doubt, add a check.
FlowFi follows the Contributor Covenant. In short: be respectful, be constructive, be patient. Aggressive, dismissive, or exclusionary behavior will result in removal from the project.
Issues are labeled by difficulty. Start here:
good-first-issue: Focused, well-scoped tasks ideal for first contributionsintermediate: Require understanding multiple parts of the codebaseadvanced: Protocol design, security hardening, or significant new featuresprotocol-design: Architectural decisions — start with a discussion before codingsecurity: Require careful analysis; please post your threat model as a comment before submitting a fix
The codebase has TODO comments throughout. Each one is a potential contribution:
# Find all TODOs
grep -rn "TODO" contracts/ sdk/If a TODO doesn't have a corresponding GitHub issue yet, open one! This itself is a valuable contribution.
Test coverage is incomplete by design. Adding tests to any contract is always welcome and a great way to understand the codebase.
Clear documentation has the highest leverage of any contribution. If you read something and had to re-read it twice to understand, that's a documentation bug.
| Tool | Version | Install |
|---|---|---|
| Rust | stable | rustup install stable |
| wasm32 target | — | rustup target add wasm32-unknown-unknown |
| Stellar CLI | >= 20.x | cargo install stellar-cli --features opt |
| Node.js | >= 18 | nodejs.org |
| npm | >= 9 | Comes with Node.js |
# 1. Fork the repository on GitHub, then clone your fork
git clone https://github.com/<your-username>/flowfi.git
cd flowfi
# 2. Add the upstream remote
git remote add upstream https://github.com/flowfi-protocol/flowfi.git
# 3. Build contracts
cargo build --target wasm32-unknown-unknown --release --workspace
# 4. Set up the SDK
cd sdk
npm install
npm run build
cd ..
# 5. Copy environment config
cp .env.example .env
# Edit .env with your testnet details (only needed for deployment/integration tests)# Run all contract tests
cargo test --workspace
# Run tests for a specific contract
cargo test -p flowfi-vault
# Run a specific test by name
cargo test -p flowfi-vault test_deposit_and_withdraw
# Run with output (useful for debugging)
cargo test --workspace -- --nocapturecd sdk
npm test
# Watch mode during development
npm test -- --watch# Integration tests require a running Soroban environment
# See tests/README.md for setup instructions
cd tests
npm install
npm testFormatting: All Rust code must be formatted with rustfmt. Run before committing:
cargo fmt --allLinting: Code must pass clippy with no warnings:
cargo clippy --workspace --all-targets -- -D warningsStyle guidelines:
- Use descriptive variable names.
shares_to_mintovers. - Every public function must have a doc comment (
///). - Every
panic!()must have a clear message explaining what invariant was violated. - Use
checked_mul/saturating_mulfor arithmetic. Never assume no overflow. - New storage keys must be added to the
DataKeyenum with a comment explaining their purpose. - Tests should follow the
Arrange → Act → Assertpattern. - Test function names should be
test_<function>_<scenario>, e.g.test_deposit_zero_amount_panics.
What we don't do:
- No
unwrap()in production paths (only in tests). Use.expect("descriptive message"). - No
unsafecode. - No
println!in contract code (use events).
Formatting: Use Prettier. Run before committing:
cd sdk && npm run formatLinting:
cd sdk && npm run lintStyle guidelines:
- All public methods and types must have JSDoc comments.
- Use
bigintfor all token amounts. Nevernumberfor on-chain values. - Error messages should be actionable:
"deposit amount must be positive"not"invalid input". - All RPC calls must have try/catch with typed error handling.
We use a simple trunk-based development model:
| Branch | Purpose |
|---|---|
main |
Stable, reviewed code. Direct pushes not allowed. |
develop |
Integration branch for upcoming release |
feat/<name> |
Feature branches (your PRs target develop) |
fix/<name> |
Bug fix branches |
docs/<name> |
Documentation-only changes |
security/<name> |
Security fixes (coordinate with maintainers first) |
Branch naming examples:
feat/multi-token-rewardsfix/vault-share-price-precisiondocs/sdk-jsdoc-coveragetest/vault-edge-cases
- Your branch is based on the latest
develop -
cargo fmt --allpasses with no changes -
cargo clippy --workspacepasses with no warnings - All existing tests pass (
cargo test --workspace) - New functionality has tests
- Public functions have doc comments
- If your PR changes protocol behavior, it has a corresponding note in
docs/
## Summary
What does this PR do? (2–3 sentences)
## Motivation
Why is this change needed? Link to the relevant issue: Closes #<issue-number>
## Changes
- Contract X: Added Y
- SDK: Updated Z
- Tests: Added coverage for W
## Testing
How did you verify this works? What edge cases did you test?
## Open Questions
Anything you're unsure about or want reviewers to focus on?- Open a draft PR early if you want early feedback
- At least one maintainer review is required to merge
- Security-related PRs require two reviews
- We aim to provide initial feedback within 5 business days
- PRs that sit without updates for 3 weeks may be closed (but can be reopened)
- Small and focused: One concern per PR. If you find yourself writing "also..." in the summary, it should probably be a separate PR.
- Test-first thinking: Show us you understand the edge cases, not just the happy path.
- Explains the why: Comments in code, description in PR — we want to understand your reasoning.
- Iterates gracefully: Responds to review feedback constructively and promptly.
| Label | Meaning |
|---|---|
good-first-issue |
Self-contained, well-scoped, ideal for first PRs |
intermediate |
Requires understanding multiple modules |
advanced |
Significant new feature or protocol change |
security |
Potential security impact — handle with care |
protocol-design |
Architectural question — start with discussion |
testing |
Improving test coverage |
documentation |
Docs, comments, examples |
sdk |
TypeScript SDK changes |
contracts |
Smart contract changes |
dx |
Developer experience improvements |
bug |
Something is broken |
research |
Exploratory — output is a design doc, not code |
help-wanted |
Maintainers want community input |
For protocol-design or advanced issues, please do not open a code PR before the design is agreed upon. The process is:
- Open a GitHub Discussion (or comment on the existing issue) with your proposed design
- Include: motivation, proposed approach, alternatives considered, risks
- Wait for maintainer sign-off (or meaningful community consensus) before writing code
- Reference the discussion in your eventual PR
This saves everyone time. A 200-line design comment is much cheaper to revise than a 2000-line PR.
If you're new to Soroban, Web3, or open source in general, here's a recommended path:
- Read docs/architecture.md in full
- Read docs/contracts.md
- Clone the repo and get the build working locally
- Run
cargo test --workspaceand see everything green - Skim the four contract files, reading all comments
- Pick a
good-first-issuethat interests you - Comment on the issue: "I'd like to work on this"
- Set up a branch and start exploring the relevant code
- Open a draft PR early — don't wait until it's perfect
- Address any review feedback
- Get your PR merged 🎉
- Leave a comment on the issue you'd want to tackle next
- Soroban Documentation
- Soroban by Example
- Stellar Developer Discord
- Rust Book — especially chapters on ownership and enums
- FlowFi Architecture Doc
- GitHub Discussions: For design questions and longer conversations
- GitHub Issues: For bug reports and feature requests
- Discord: Join the FlowFi server for real-time chat
We're glad you're here. Let's build something great for the Stellar ecosystem together.