Thank you for your interest in contributing to StellarForge! This document provides guidelines for contributing to our collection of Soroban smart contracts.
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes
- Run tests:
make testorcargo test --workspace - Create Pull Request for Code Review
We follow the Conventional Commits specification for clear and consistent commit history.
<type>(<scope>): <subject>
<body>
<footer>
Must be one of the following:
- feat: A new feature
- fix: A bug fix
- docs: Documentation only changes
- style: Changes that don't affect code meaning (whitespace, formatting)
- refactor: Code change that neither fixes a bug nor adds a feature
- perf: Performance improvement
- test: Adding or updating tests
- chore: Changes to build process or auxiliary tools
- revert: Reverts a previous commit
The scope should specify the contract or component affected:
forge-streamforge-vestingforge-governorforge-multisigforge-oracleforge-vesting-factoryforge-errorsdocsci
- Use imperative, present tense: "add" not "added" or "adds"
- Don't capitalize first letter
- No period (.) at the end
- Limit to 50 characters
- Explain what and why, not how
- Wrap at 72 characters
- Separate from subject with blank line
- Reference issues:
Closes #123,Fixes #456,Resolves #789 - Note breaking changes:
BREAKING CHANGE: description
Simple feature:
feat(forge-stream): add pause functionality
Allows stream sender to temporarily pause token accrual.
Bug fix with issue reference:
fix(forge-oracle): return error instead of None when uninitialized
Changes get_admin() and get_staleness_threshold() to return
Result types for consistent error handling.
Fixes #224
Multiple changes:
feat(forge-multisig): add event emission to all state changes
- Add proposal_created event
- Add proposal_approved event
- Add proposal_rejected event
- Add proposal_executed event
Closes #226
Breaking change:
refactor(forge-vesting)!: change claim() return type
BREAKING CHANGE: claim() now returns Result<i128, VestingError>
instead of i128. Callers must handle the Result type.
Closes #123
- Keep commits atomic - One logical change per commit
- Write meaningful messages - Future you will thank you
- Reference issues - Use
Closes #123orFixes #456in footer - Use present tense - "add feature" not "added feature"
- Be concise but descriptive - Balance brevity with clarity
- Separate subject from body - Use blank line between them
- Wrap body at 72 characters - For better readability in git log
When adding new common error variants to forge-errors:
- Consider if the error is truly common across multiple contracts
- Add descriptive documentation to the variant in
crates/forge-errors/src/lib.rs - Update error codes to avoid conflicts with existing variants
- Test the change across all affected contracts
If you identify an error pattern that appears in 3+ contracts, consider adding it to CommonError:
#[contracterror]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CommonError {
// Existing variants...
/// New error description
NewError = NEXT_AVAILABLE_CODE,
}Process:
- Add the variant to
CommonErrorwith next available error code - Update any contracts that should use this new shared variant
- Add tests to verify the error behavior
- Update documentation
- Rust: 2021 edition with
wasm32v1-nonetarget - Stellar CLI: v25.2.0 or higher
- Make: (optional) for convenience commands
# Install Rust
rustup target add wasm32v1-none
# Install Stellar CLI
cargo install --locked stellar-cli
# Verify installation
stellar --version# Test all contracts
make test
# Test specific contract
cargo test -p forge-governor
cargo test -p forge-multisig
cargo test -p forge-oracle
cargo test -p forge-stream
cargo test -p forge-vesting
cargo test -p forge-vesting-factoryWe aim for high test coverage. When adding new features:
- Write unit tests for new functionality
- Test error paths exhaustively
- Include integration tests for contract interactions
- Verify all error variants are tested
Follow these conventions:
- Use
rustfmtfor formatting:make fmt - Use
clippyfor linting:make lint - Follow Rust idioms and Soroban best practices
- Use
#![no_std]for all contracts - Prefer
require_auth()over manual auth checks where possible
- Error Handling: Use the shared
CommonErrorvariants when applicable - Storage: Use appropriate storage types (instance vs persistent)
- Events: Emit events for all state changes
- TTL Management: Extend storage TTLs appropriately
- Security: Follow established security patterns from existing contracts
- Document all public functions with examples
- Include error conditions in docstrings
- Update README.md for new features
- Keep CHANGELOG.md updated
When reporting bugs:
- Use the issue template provided in GitHub Issues
- Include reproduction steps with minimal example
- Specify contract name and affected functions
- Include environment details (OS, Rust version, Stellar CLI version)
- Add logs and error messages when applicable
We welcome feature requests! Please:
- Check existing issues for similar requests
- Describe the use case clearly
- Consider impact on existing contracts and integrators
- Propose implementation approach if you have ideas
- Tests pass:
make test - Code formatted:
make fmtorcargo fmt --all - Linting clean:
make lintorcargo clippy --workspace -- -D warnings - Documentation updated
- CHANGELOG.md updated (if applicable)
- Branch follows naming convention (feat/, fix/, docs/, etc.)
- Small, focused PRs are preferred over large, multi-purpose changes
- One feature per PR when possible
- Include tests for new functionality
- Update documentation as needed
- Link to related issues using "Closes #123" or "Fixes #456" in the PR description
- Provide context in the PR description explaining what changed and why
Maintainers will review for:
- ✅ Code quality and style
- ✅ Test coverage
- ✅ Security considerations
- ✅ Documentation completeness
- ✅ Breaking changes (if any)
Security is our top priority. If you discover a security vulnerability:
- Do NOT open a public issue
- Email us privately: security@stellarforge.org
- Include details: Impact, reproduction steps, affected versions
- Allow time for response: We'll acknowledge within 48 hours
build:
cargo build --workspace
test:
cargo test --workspace
fmt:
cargo fmt --all
lint:
cargo clippy --workspace -- -D warnings
check:
cargo fmt --all && cargo clippy --workspace -- -D warnings && cargo test --workspace
clean:
cargo clean --workspacestellarforge/
├── crates/
│ └── forge-errors/ # Shared error library
├── contracts/
│ ├── forge-governor/ # Governance contract
│ ├── forge-multisig/ # Multisig treasury
│ ├── forge-oracle/ # Price feed contract
│ ├── forge-stream/ # Token streaming
│ ├── forge-vesting/ # Token vesting
│ └── forge-vesting-factory/ # Multi-beneficiary vesting
├── benches/ # Performance benchmarks
└── scripts/ # Utility scripts
- GitHub Discussions: Use for questions, ideas, and general discussion
- Issues: Bug reports and feature requests
- Discord: Join our community for real-time chat
By contributing, you agree that your contributions will be licensed under the same MIT License as the project.
Thank you for contributing to StellarForge! 🚀