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 - When adding or renaming an error variant in
contracts/escrow/src/errors.rsorcontracts/oracle/src/errors.rs: updatedocs/error-codes.mdin the same PR — add a new row to the relevant table with theSincecolumn set to the next version, and add an entry to the Error Code Changelog section at the bottom of that file.
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
The escrow contract's public ABI is protected by a snapshot check in CI
(.github/workflows/abi-snapshot.yml). If you intentionally add, remove, or
rename a public function in contracts/escrow/src/lib.rs, you must update
the baseline before merging or CI will fail.
Procedure:
-
Build the escrow contract for release:
cd contracts/escrow cargo build --target wasm32-unknown-unknown --release -
Inspect the WASM to get the current function list:
stellar contract inspect \ --wasm ../../target/wasm32-unknown-unknown/release/escrow.wasm \ --output json > /tmp/current-spec.json -
Update
contracts/escrow/contract-spec.json:- Add a new
{ "name": "your_function" }entry to the"functions"array for each new function, or remove the entry for deleted functions. - Update
"_generated_at"to today's date. - Commit the updated file as part of your PR.
- Add a new
-
Add a changelog entry in
CHANGELOG.mddescribing the ABI change:### Changed - Added `your_function` to the escrow contract public ABI (since v0.X.0).
-
Update
docs/error-codes.mdif the change introduces or removes error variants (see the Since column requirement above).
Why this matters: The escrow ABI is effectively a public interface. Clients (oracle service, frontend, third-party integrators) depend on stable function names and signatures. An accidental rename or removal can silently break live integrations. The snapshot check catches these regressions at PR review time, not in production.
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.