Both players get their stakes back. The escrow holds 2 × stake_amount, and when the oracle submits a draw result, each player receives 1 × stake_amount back. No one wins the full pot.
is_funded(match_id)— returnstrueonly when both players have deposited. It gates whether the game can legally start. Use this to check if the match is ready to play.get_escrow_balance(match_id)— returns the total amount currently held in escrow:0,1 × stake, or2 × stake. Once a match is completed or cancelled (payouts done), this returns0.
| Scenario | is_funded |
get_escrow_balance |
|---|---|---|
| Only player1 deposited | false |
1 × stake |
| Both deposited (Active) | true |
2 × stake |
| Completed (payout done) | true |
0 |
| Cancelled (refunds done) | false |
0 |
If a match is stuck in Pending (one player deposited but the other didn't), either:
- Wait for timeout — call
expire_matchafter the configured timeout elapses (default: 30 days). This refunds the depositor. - Cancel before timeout — if you're a player in the match, call
cancel_matchto cancel it immediately (only works if the match is stillPending, i.e., not yetActive).
Check get_match_timeout() to see the current timeout, and get_match(match_id) to see when it was created.
No. Once a match transitions to Active (both players deposited), only the oracle submitting a result or the timeout expiring can end it. This prevents one player from backing out mid-game. See error code #19.
Payouts settle in seconds once the oracle submits the result on-chain. Stellar's fast finality means the winner's account receives the funds within the block confirmation time (~5–6 seconds).
The oracle is a trusted intermediary that bridges off-chain game data (Lichess, Chess.com) to the on-chain contract. It verifies the game result and submits it. If the oracle is compromised or malicious, it could submit false results. This is unavoidable in the current design — the contract has no way to independently verify that a Lichess game happened or who won.
Mitigation: The oracle service is run by the maintainers and operated transparently. Future versions may use decentralized oracle networks (e.g., Chainlink) or cryptographic game proofs to reduce trust.
Resubmit the result once the oracle is back online. As long as the result is submitted within the Soroban TTL window (typically a few ledger slots, but kept generous via ledger snapshot retention), the payout will process. Avoid submitting results extremely late (weeks later) — the ledger snapshot needed for verification may be purged. See error code #21.
No. Only the configured oracle address can call submit_result (or submit_result_with_oracle_record). Players don't have authorization. This prevents disputes over who won — the oracle is the single source of truth.
- Use
stellar keys generateto create a testnet account. - Fund it with free testnet tokens via the Stellar Testnet Faucet.
- Create matches with small stake amounts on the testnet contract (configured in
.envasSTELLAR_NETWORK=testnet). - Follow the Interactive Tutorial for a step-by-step walkthrough.
Testnet tokens have zero real value — no financial risk.
- Testnet: Tokens are test-only. Contracts are frequently updated. Use for learning and integration testing.
- Mainnet: Real tokens with real value. Contract code is audited and stable. Players risk actual funds. Always verify the contract address before sending real money.
Check STELLAR_NETWORK in .env to confirm which network you're on. Testnet RPC: https://soroban-testnet.stellar.org. Mainnet RPC: https://soroban-mainnet.stellar.org.
By default, any Stellar token address is accepted. However, once the admin calls add_allowed_token with at least one token, the contract only accepts tokens on the allowlist. Call get_allowed_tokens() to see which tokens are currently allowed.
You'll get error code #17. Ask the admin to either:
- Add your token via
add_allowed_token, or - Use a token already on the allowlist.
The admin can:
- Add/remove allowed tokens
- Pause/unpause the contract (blocks new matches, deposits, and result submissions)
- Update the oracle address
- Set the match timeout
- Transfer admin rights to another account
The admin cannot directly cancel matches or refund stuck stakes — only expire_match, cancel_match, or player actions do that.
Use a two-step process:
- Current admin calls
propose_admin(new_admin_address). - New admin calls
accept_admin()to confirm.
This prevents mistakes like typos in the new admin address. If the new admin rejects or doesn't accept, rights stay with the current admin.
Either:
- You're signing with the wrong keypair (not the admin, oracle, or depositing player).
- The contract hasn't been
initialized yet.
Check is_initialized() and verify your signer. If initializing, ensure you're passing the correct admin and oracle addresses.
For detailed error reference, see Error Codes Reference.