Thanks for your interest in contributing to Checkmate-Escrow! This guide will help you get started.
- Rust 1.70 or later
- Soroban CLI
- Stellar CLI
- Git
- Fork the repository
- Clone your fork:
git clone https://github.com/your-username/checkmate-escrow.git cd checkmate-escrow - Set up your environment:
cp .env.example .env # Edit .env with your configuration - Build the project:
./scripts/build.sh
- Run tests to verify your setup:
./scripts/test.sh
Create a feature branch from main:
git checkout -b feature/your-feature-nameUse descriptive branch names:
feature/for new featuresfix/for bug fixesdocs/for documentation updatesrefactor/for code refactoring
- Write clear, concise commit messages
- Keep commits focused on a single change
- Add tests for new functionality
- Update documentation as needed
Run the full test suite before submitting:
cargo testFor specific contract tests:
cargo test -p escrow
cargo test -p oracle- Follow Rust standard formatting:
cargo fmt - Run clippy for linting:
cargo clippy - Keep functions small and focused
- Add comments for complex logic
- Use descriptive variable names
- Update relevant documentation in
docs/for architectural changes - Add inline comments for non-obvious code
- Add or update Soroban contract guidance in
docs/contributing-contracts.mdwhen changing contract storage, TTL, or auth behavior - Add or update oracle guidance in
docs/CONTRIBUTING_ORACLE.mdwhen changing the oracle service, adding platform clients, or modifying result verification - Update README.md if adding new features or changing setup steps
- Check repository health and link validity with
./scripts/repository_health_check.sh
See docs/repository-health-checklist.md for checklist details.
Every pull request must include a changelog entry. This keeps the release history accurate and helps reviewers understand the impact of a change at a glance.
Open CHANGELOG.md and add your entry under the ## [Unreleased] section at the top of the file. If that section does not exist yet, add it directly below the introductory paragraph.
The project follows the Keep a Changelog convention. Use one of these subsection headings — add only the ones that apply:
## [Unreleased]
### Added
- Short description of a new feature or capability.
### Changed
- Short description of a change to existing behavior.
### Fixed
- Short description of a bug that was fixed.
### Removed
- Short description of something that was removed.Copy the block below into CHANGELOG.md under ## [Unreleased] and delete the subsections you don't need:
### Added
- <!-- Describe new features or functions introduced by this PR -->
### Changed
- <!-- Describe modifications to existing behavior, APIs, or configuration -->
### Fixed
- <!-- Describe bugs or incorrect behavior that this PR corrects -->
### Removed
- <!-- Describe features, flags, or APIs that were deleted -->- Write entries from the perspective of a user or integrator, not an implementer. Explain what changed and why it matters, not how the code was restructured.
- Use the past tense and start with a capital letter:
Added support for …,Fixed incorrect payout when … - One bullet per logical change. If a PR touches multiple independent areas, add one bullet for each.
- Do not include internal refactors or test-only changes unless they affect observable behavior.
- When a version is released, maintainers will move
[Unreleased]entries into a new versioned section (e.g.## [1.1.0] - 2026-08-01). You don't need to do this yourself.
- Push your branch to your fork:
git push origin feature/your-feature-name
- Open a Pull Request against the
mainbranch - Fill out the PR template with:
- Clear description of changes
- Related issue numbers (if applicable)
- Testing performed
- Screenshots (for UI changes)
- Wait for review and address feedback
- Keep PRs focused on a single feature or fix
- Ensure all tests pass
- Update documentation
- Respond to review comments promptly
- Squash commits if requested
The repository uses a CODEOWNERS file to automatically request reviews from designated maintainers when changes touch critical areas:
- Smart contracts (
/contracts/escrow/,/contracts/oracle/): Reviewed by @StellarCheckMate/contracts team - CI/CD and build configuration (
/.github/,/scripts/): Reviewed by @StellarCheckMate/maintainers - Documentation (
/docs/): Reviewed by @StellarCheckMate/docs team - Other changes: Reviewed by @StellarCheckMate/maintainers
When a PR touches files in these paths, GitHub automatically requests review from the designated owners. This ensures that security-critical contract code and infrastructure changes receive appropriate scrutiny. All requested reviews must be approved before merging.
We use a shared label taxonomy to keep issue and PR triage consistent. See docs/label-taxonomy.md for definitions of labels like good first issue, wave-ready, and help-wanted.
- Use
snake_casefor functions and variables - Use
PascalCasefor types and enums - Prefer explicit error handling over panics
- Use
Result<T, Error>for fallible operations - Document public APIs with doc comments
- Validate all inputs at function entry
- Use appropriate storage types (instance, persistent, temporary)
- Extend TTL for long-lived data
- Emit events for state changes
- Require authentication for privileged operations
- Write unit tests for all public functions
- Test error cases and edge conditions
- Use descriptive test names:
test_function_name_condition_expected_result - Mock external dependencies
- Verify events are emitted correctly
For a comprehensive guide on writing tests, see Testing Guide which covers:
- Soroban test environment setup
- Mocking addresses and tokens
- Test organization and patterns
- Complete annotated example tests
When testing that a contract function returns a specific error, prefer the typed
try_ variant over #[should_panic]. The try_ approach asserts the exact
error variant, making failures easier to diagnose and preventing tests from
accidentally passing due to an unrelated panic.
Avoid — #[should_panic] only checks that something panicked:
#[test]
#[should_panic(expected = "Error(Contract, #10)")]
fn test_create_match_with_zero_stake_fails() {
let (env, contract_id, _oracle, player1, player2, token, _admin) = setup();
let client = EscrowContractClient::new(&env, &contract_id);
client.create_match(&player1, &player2, &0, &token,
&String::from_str(&env, "game"), &Platform::Lichess);
}Prefer — try_ asserts the exact error variant:
#[test]
fn test_create_match_with_zero_stake_returns_invalid_amount() {
let (env, contract_id, _oracle, player1, player2, token, _admin) = setup();
let client = EscrowContractClient::new(&env, &contract_id);
let result = client.try_create_match(&player1, &player2, &0, &token,
&String::from_str(&env, "game"), &Platform::Lichess);
assert_eq!(result, Err(Ok(Error::InvalidAmount)));
}Use #[should_panic] only for cases where the contract panics with a plain
string message rather than a typed error (e.g. double-initialization):
#[test]
#[should_panic(expected = "Contract already initialized")]
fn test_double_initialize_fails() {
// ...
client.initialize(&oracle, &admin);
client.initialize(&oracle, &admin); // panics with a string, not a typed Error
}For changes to contracts/escrow or contracts/oracle, see docs/contributing-contracts.md for detailed guidance on:
- Authorization patterns and
require_auth - Storage tiers and state layout
- TTL management
- Contract initialization and upgrade safety
- Events and observability
For changes to the off-chain oracle service, see docs/CONTRIBUTING_ORACLE.md for detailed guidance on:
- Local oracle setup and environment configuration
- Running and writing oracle integration tests
- Adding support for new chess platform clients
- Result verification and security patterns
- API rate limiting and error handling
Checkmate-Escrow participates in Drips Wave contributor funding. Issues labeled wave-ready are eligible for funding:
trivial(100 points): Documentation, simple tests, minor fixesmedium(150 points): Oracle helpers, validation logic, moderate featureshigh(200 points): Core escrow logic, Oracle integrations, security enhancements
See docs/wave-guide.md for details on earning funding.
- Open an issue for bugs or feature requests
- Join discussions in existing issues
- Ask questions in pull request comments
Please read and follow our Code of Conduct.
By contributing, you agree that your contributions will be licensed under the MIT License.