A trustless chess wagering platform built on Stellar Soroban smart contracts. Players stake tokens before a match, and the winner is automatically paid out the moment the game ends β no middleman, no delays, no trust required.
Checkmate-Escrow combines competitive chess with Stellar's fast settlement to create a fully on-chain betting platform for casual and high-stakes matches.
Players:
- Stake tokens into a Soroban escrow contract before a match begins
- Play their game on Lichess or Chess.com as normal
- Receive automatic payouts the instant the match result is verified on-chain
A custom Oracle bridges the Chess.com / Lichess API to the smart contract, verifying match results and triggering payouts without any manual intervention.
This makes Checkmate-Escrow:
β
Trustless (no platform can withhold or delay winnings)
β
Transparent (all stakes and payouts are verifiable on-chain)
β
Instant (Stellar's fast finality means payouts settle in seconds)
β
Accessible (anyone with a Stellar wallet can participate)
- Create a Match: Set stake amount, token address, and link a Lichess/Chess.com game ID
- Flexible Token Support: Any Stellar token address is accepted by default; once the admin adds at least one token via
add_allowed_token, only allowlisted tokens are accepted for new matches - Escrow Stakes: Both players deposit funds into the contract before the game starts
- Oracle Integration: Real-time result verification via Lichess/Chess.com APIs
- Automatic Payouts: Winner receives the full pot the moment the result is confirmed
- Draw Handling: Stakes are returned to both players in the event of a draw
- Admin Controls: Pause/unpause, oracle rotation, admin transfer, and match timeout configuration
- Transparent: All escrow balances and payout history are verifiable on-chain
Matches move through the following states:
Pending βββΊ Active βββΊ Completed
β β²
ββββΊ Cancelled ββββββββββ
(expire_match / cancel_match)
| State | Description |
|---|---|
Pending |
Match created; awaiting deposits from both players |
Active |
Both players have deposited; game is in progress |
Completed |
Oracle submitted result; payout executed |
Cancelled |
Cancelled before activation, or expired after timeout |
| Topic (namespace / name) | Emitted by | Payload |
|---|---|---|
escrow / init |
initialize |
(oracle_address, admin_address) |
admin / paused |
pause |
() |
admin / unpaused |
unpause |
() |
admin / oracle_up |
update_oracle |
(old_oracle, new_oracle) |
admin / xfer |
transfer_admin |
(old_admin, new_admin) |
match / created |
create_match |
(match_id, player1, player2, stake_amount) |
match / completed |
submit_result |
(match_id, winner) |
match / cancelled |
cancel_match |
match_id |
match / expired |
expire_match |
match_id |
- Rust (1.70+)
- Soroban CLI
- Stellar CLI
./scripts/build.sh./scripts/test.shCopy the example environment file:
cp .env.example .envConfigure your environment variables in .env:
# Network configuration
STELLAR_NETWORK=testnet
STELLAR_RPC_URL=https://soroban-testnet.stellar.org
# Contract addresses (after deployment)
CONTRACT_ESCROW=<your-contract-id>
CONTRACT_ORACLE=<your-contract-id>
# Oracle configuration
LICHESS_API_TOKEN=<your-lichess-api-token>
CHESSDOTCOM_API_KEY=<your-chessdotcom-api-key>
# Frontend configuration
VITE_STELLAR_NETWORK=testnet
VITE_STELLAR_RPC_URL=https://soroban-testnet.stellar.orgNetwork configurations are defined in environments.toml:
testnetβ Stellar testnetmainnetβ Stellar mainnetfuturenetβ Stellar futurenetstandaloneβ Local development
# Configure your testnet identity first
stellar keys generate deployer --network testnet
# Deploy
./scripts/deploy_testnet.shFollow the step-by-step guide in demo/demo-script.md
create_match(player1, player2, stake_amount, token, game_id, platform) -> u64
get_match(match_id) -> Match
cancel_match(match_id, caller)
expire_match(match_id)
get_player_matches(player) -> Vec<u64>
get_active_matches() -> Vec<u64>
deposit(match_id, player)
is_funded(match_id) -> bool
get_escrow_balance(match_id) -> i128
These two functions answer different questions and are easy to confuse:
-
is_funded(match_id)β returnstrueonly when both players have deposited their stake (i.e. the match has transitioned toActive). It reflects deposit flags, not token balances. Use this to gate game-start logic. -
get_escrow_balance(match_id)β returns the total token amount currently held in escrow for the match:0,1Γstake, or2Γstakedepending on how many players have deposited. Once a match isCompletedorCancelled(funds already paid out or refunded), this always returns0regardless of on-chain token balances.
Examples:
| Scenario | is_funded |
get_escrow_balance |
|---|---|---|
| Only player1 deposited | false |
1 Γ stake_amount |
| Both players deposited (Active) | true |
2 Γ stake_amount |
| Match completed (payout done) | true |
0 |
| Match cancelled (refunds done) | false |
0 |
submit_result(match_id, winner)
has_result(match_id) -> bool
get_result(match_id) -> ResultEntry
submit_result is called by the trusted oracle address. It verifies the caller, records the winner, and immediately executes the payout (or refund on draw) in a single transaction. There are no separate verify_result or execute_payout functions.
Comprehensive test suite covering:
β
Match creation and configuration
β
Deposit validation and escrow locking
β
Oracle result submission and verification
β
Winner payout and draw refund logic
β
Cancellation and edge cases
β
Error handling and security checks
Run tests:
cargo testThe Problem: Current chess betting and tournament prize payouts are slow and rely entirely on the platform's honesty. Players have no guarantee their winnings will be paid out fairly or on time.
The Solution: By holding stakes in a Soroban smart contract and automating payouts via a verified Oracle, Checkmate-Escrow removes the need to trust any third party.
Blockchain Benefits:
- No platform can withhold or manipulate payouts
- Transparent stake and payout history for every match
- Programmable rules enforced by smart contracts
- Accessible to anyone with a Stellar wallet
Target Users:
- Competitive chess players looking for trustless wagering
- Chess clubs and tournament organizers
- Casual players wanting skin-in-the-game matches
- Developers building on Stellar/Soroban
- v1.0 (Current): Token-allowlist escrow, Lichess Oracle integration, basic match flow
- v1.1: Chess.com Oracle, expanded token support
- v2.0: Multi-game tournaments, bracket payouts
- v3.0: Frontend UI with wallet integration
- v4.0: Mobile app, ELO-based matchmaking, leaderboards
See docs/roadmap.md for details.
We welcome contributions! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See our Code of Conduct and Contributing Guidelines.
This project participates in Drips Wave β a contributor funding program! Check out:
- Wave Contributor Guide β How to earn funding for contributions
- Wave-Ready Issues β Funded issues ready to tackle
- GitHub Issues labeled with
wave-readyβ Earn 100β200 points per issue
Issues are categorized as:
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
This project is licensed under the MIT License β see the LICENSE file for details.
- Stellar Development Foundation for Soroban
- Lichess for their open API
- Chess.com for their developer platform
- Drips Wave for supporting public goods funding