A curated collection of production-ready Soroban smart contract templates. These templates help developers quickly bootstrap common use cases on Soroban (Stellar's smart contract platform) for DeFi, payments, governance, and more.
TambiΓ©n disponible en: EspaΓ±ol πͺπΈ
# Clone the repository
git clone https://github.com/your-username/soroban-contract-templates.git
cd soroban-contract-templates
# Build all contracts
make build
# Run tests
make test
# Re-run tests automatically on file changes (requires cargo-watch)
make watch
# Deploy to testnet
make deploy-testnet
# See all available commands
make helpOr use just (see dev-environment.md for installation):
just build
just test
just deploy-testnet
just --list| Template | Description | Use Cases | Status |
|---|---|---|---|
| Token | Custom fungible token with mint/burn/admin controls | DeFi tokens, governance tokens, utility tokens | β Complete |
| Escrow | Two-party escrow with timeout and refund mechanism | P2P trading, service payments, milestone payments | β Complete |
| Vesting | Token vesting with cliff + linear release schedule | Team allocations, investor lockups, employee grants | β Complete |
| Staking | Token staking with proportional reward distribution | DeFi yield, protocol incentives, liquidity mining | β Complete |
| Multisig | N-of-M wallet for threshold-approved contract calls | DAO treasuries, team wallets, shared administration | β Complete |
| Subscription | Recurring token-pull payment contract | SaaS billing, streaming payments, membership fees | β Complete |
| Timelock | Time-locked token release to a beneficiary | Team token locks, delayed payments, governance timelocks | β Complete |
| NFT | Non-fungible token with admin minting and optional supply cap | Digital collectibles, on-chain ownership, access tokens | β Complete |
| DAO | On-chain governance with token-weighted voting | Protocol upgrades, treasury management, community decisions | β Complete |
| Swap | Atomic two-party token swap with deadline | P2P token exchange, OTC trades, trustless DeFi swaps | β Complete |
| Oracle | Price oracle consumer with staleness validation | DeFi price feeds, on-chain data consumption, freshness checks | β Complete |
| Lottery | Verifiable on-chain lottery with commit-reveal randomness | Raffles, fair draws, decentralised prize distribution | β Complete |
- Standard Interface: Full Soroban token compatibility
- Administrative Controls: Mint, burn, and admin management
- Metadata Support: Name, symbol, and decimals
- Allowance System: Approve and transfer_from functionality
- Event Emission: All operations emit events for tracking
- Error Handling: Custom error types for better debugging
- Two-Party Security: Secure buyer-seller transactions
- Deadline Protection: Automatic refunds after deadline
- Arbiter Support: Third-party dispute resolution
- State Management: Clear transaction lifecycle
- Token Agnostic: Works with any Soroban token
- Event Emission: All operations emit events for tracking
- Cliff + Linear Schedule: Tokens unlock linearly between
cliff_ledgerandend_ledger - Admin Revocation: Admin can cancel unvested tokens at any time; vested tokens remain claimable
- Incremental Claims: Beneficiary claims accrued tokens on demand
- Token Agnostic: Works with any Soroban-compatible token
- Event Emission:
initialized,claimed, andrevokedevents for off-chain tracking - TTL Management: Instance storage TTL is extended on every interaction
- Proportional Rewards: Rewards distributed pro-rata to each staker's share of the pool
- Reward-Per-Token Accumulator: Gas-efficient global accumulator pattern; no per-staker loops
- Separate Stake / Reward Tokens: Stake token and reward token can be the same or different
- Admin Reward Deposits: Admin calls
add_rewardsto top up the reward pool at any time - Incremental Claims: Stakers call
claim_rewardsindependently; rewards accrue continuously - Token Agnostic: Works with any Soroban-compatible token
- Event Emission:
staked,unstaked,rewards_claimed, andrewards_addedevents - TTL Management: Instance storage TTL is extended on every interaction
- Provider-Initiated Charges: Service provider pulls payments on a configurable ledger interval
- Subscriber-Controlled Plans: Subscribers set their own amount and interval; cancel at any time
- Allowance-Based Pulls: Uses token
approve+transfer_fromβ no funds are locked up-front - Re-subscribe Support: Cancelled subscribers can create a new plan without re-deploying
- State Tracking: Subscription state (active, last charged ledger) stored per subscriber
- Event Emission:
subscribed,charged, andcancelledevents for off-chain tracking - TTL Management: Both instance and persistent storage entries are extended on each interaction
- N-of-M Authorization: Configure any valid threshold across unique signers
- Signer Management: Add or remove signers with threshold-approved changes
- Transaction Proposals: Store target contract, function, and arguments
- Signature Tracking: Prevent duplicate signatures and non-signer approvals
- Threshold Execution: Execute proposed calls only after enough signatures
- Event Emission: Initialization, signer changes, signatures, and execution emit events
- Time-Locked Release: Tokens held until a specified ledger sequence number, then released to the beneficiary
- Admin Cancellation: Admin can cancel and reclaim tokens at any time before release
- Open Release: Once the release ledger is reached,
releaseis callable by anyone - Token Agnostic: Works with any Soroban-compatible token
- Event Emission:
initialized,released, andcancelledevents for off-chain tracking - TTL Management: Instance storage TTL is extended on every interaction
- Unique Token Ownership: Each token ID maps to exactly one owner tracked in persistent storage
- Admin-Controlled Minting: Only the admin may mint new tokens; optional supply cap enforced at mint time
- Standard Operations:
mint,transfer,burn,approve,transfer_frommatching ERC-721 semantics - Per-Token Metadata: Each token has an associated URI stored on-chain; collection has name and symbol
- Approval System: Single-token approvals cleared automatically on transfer or burn
- Property Tests: Proptest suite verifies supply invariants and ownership correctness
- Event Emission:
minted,transferred,burned, andapprovedevents
- Token-Weighted Voting: Voting power equals the voter's token balance at vote time
- Configurable Parameters: Voting period (in ledgers) and quorum threshold set at initialization
- Proposal Lifecycle:
Active β Executed(passes) orActive β Cancelled(admin) - Quorum + Majority: Proposals execute only when total votes β₯ quorum AND yes > no
- Double-Vote Prevention: Each address may vote exactly once per proposal
- Event Emission:
proposal_created,voted,prop_executed, andprop_cancelledevents - TTL Management: Persistent proposal and vote records are bumped on every write
- Atomic Exchange: Both token transfers occur in a single transaction β no partial fills
- Deadline-Based Expiry: Swaps expire after a configurable ledger; anyone may cancel to recover party A's tokens
- Party A Control: Party A can cancel any open swap before it is accepted
- Multi-Swap Support: Multiple concurrent swaps tracked by auto-incrementing IDs
- Token Agnostic: Works with any pair of Soroban-compatible tokens
- Event Emission:
swap_proposed,swap_accepted, andswap_cancelledevents
- Price Feed Consumer: Admin pushes price updates; consumers read via
get_price - Staleness Validation:
get_pricerejects prices older than the configured ledger threshold - Admin-Controlled Updates: Only the admin may push new prices
- Configurable Threshold: Staleness threshold set at initialization
- Event Emission:
initializedandprice_updatedevents - TTL Management: Instance storage TTL is extended on every interaction
- Commit-Reveal Randomness: Admin commits
hash(secret ++ salt)before the draw, then reveals to prove fairness - Ticket Purchase: Any address buys tickets before the admin commits
- Verifiable Winner Selection: Winner index derived from SHA-256 of revealed secret, salt, and ledger sequence
- Prize Pool Distribution: Full ticket pool transferred to winner atomically
- State Machine: Open β Committed β Drawn β each transition is irreversible
- Event Emission:
initialized,ticket_purchased,committed, andwinner_drawnevents
Each template includes:
- β Complete contract implementation
- β Comprehensive unit tests (8+ test cases each)
- β Deployment scripts with examples
- β Usage examples and documentation
- Rust 1.82.0 (pinned via
rust-toolchain.tomlβrustuppicks this up automatically) - Soroban CLI
- Docker (for local Stellar node)
Zero-install option: Open this repo in a pre-configured environment with all tools ready β see the Dev Container & Codespaces Guide.
A .vscode/extensions.json file is included with recommended extensions for a consistent developer experience. VS Code will prompt you to install them when you open the project, or you can install them manually:
| Extension | Purpose |
|---|---|
rust-lang.rust-analyzer |
Rust language server (completions, go-to-def, inline errors) |
tamasfe.even-better-toml |
Syntax highlighting and validation for Cargo.toml |
serayuzgur.crates |
Inline crate version hints and outdated-dependency warnings |
usernamehw.errorlens |
Inline diagnostic messages directly in the editor |
This repository is pinned to soroban-sdk = "=21.7.7". Each major SDK version is tightly coupled to a Stellar network protocol version. Use the table below to pick the right SDK for your target network.
β οΈ Always verify compatibility before deploying to Mainnet. Contracts compiled against SDK v21 will not work on a node running Protocol 22 or later without recompilation against the matching SDK version.
| soroban-sdk version | Stellar Protocol | Network status | Notes |
|---|---|---|---|
21.x (this repo: 21.7.7) |
Protocol 21 | Mainnet (Jun 2024) | secp256r1, separate TTL extension for instance/code |
22.x |
Protocol 22 | Mainnet (Dec 2024) | Constructor support, BLS12-381 host functions |
23.x |
Protocol 23 "Whisk" | Mainnet (Sep 2025) | Unified events (CAP-67), state archival (CAP-62/66) |
25.x |
Protocol 25 "X-Ray" | Mainnet (Jan 2026) | BN254 elliptic curve ops, Poseidon hash functions |
26.x |
Protocol 26 "Yardstick" | Mainnet (May 2026) | Freeze ledger entries, muxed address conversions, ZK BN254 |
To upgrade this repository to a newer SDK:
- Update
soroban-sdk = "=<new-version>"inCargo.toml. - Update
stellar-clito the matching version (cargo install stellar-cli --version <new-version>). - Rebuild all contracts and run the full test suite.
- Update this matrix and
docs/gas-costs.mdwith the new protocol version and fee schedule.
For the authoritative version table, see Stellar Software Versions.
cd contracts/[template-name]
stellar contract buildcd contracts/[template-name]
cargo testcd contracts/[template-name]
./scripts/deploy.sh testnetStart a local Stellar node with Soroban RPC:
docker compose up stellar-nodeScaffold a fresh contract from the contracts/common skeleton with a single command:
./scripts/new-contract.sh <contract-name>Example β create a price-feed contract:
./scripts/new-contract.sh price-feedThis creates contracts/price-feed/ (with Cargo.toml and src/lib.rs) and registers it in the workspace. Verify it compiles and its test passes immediately:
cargo check -p soroban-price-feed
cargo test -p soroban-price-feedThen replace the stub hello() method in contracts/price-feed/src/lib.rs with your contract logic.
For full details β causes, triggers, and resolution steps β see docs/error-reference.md.
| Code | Name | Description |
|---|---|---|
| 1 | InsufficientBalance |
Caller's balance is too low to complete the transfer or burn |
| 2 | InsufficientAllowance |
Approved allowance is too low for the requested transfer_from amount |
| 3 | Unauthorized |
Caller is not the admin or does not have permission for this operation |
| 4 | AlreadyInitialized |
initialize was called on a contract that has already been set up |
| 5 | NotInitialized |
An operation was attempted before the contract was initialized |
| 6 | InvalidAmount |
Amount is zero, negative, or exceeds the configured max supply |
| 7 | Overflow |
Arithmetic overflow occurred during a balance or supply calculation |
| Code | Name | Description |
|---|---|---|
| 1 | NotAuthorized |
Caller is not permitted to invoke this function (wrong party or arbiter) |
| 2 | InvalidState |
The escrow is not in the required state for this operation |
| 3 | DeadlinePassed |
The escrow deadline has already elapsed; the operation is no longer valid |
| 4 | DeadlineNotReached |
The deadline has not yet passed; premature refund or timeout claim attempted |
| 5 | AlreadyInitialized |
initialize was called on an escrow that is already set up |
| 6 | NotInitialized |
An operation was attempted before the escrow was initialized |
| 7 | InsufficientFunds |
The buyer's token balance is too low to cover the escrowed amount |
| 8 | InvalidAmount |
The specified amount is zero or otherwise invalid |
| 9 | InvalidParties |
Buyer, seller, or arbiter addresses are invalid or conflict with each other |
| Code | Name | Description |
|---|---|---|
| 1 | AlreadyInitialized |
initialize was called on a contract that is already set up |
| 2 | NotInitialized |
An operation was attempted before the contract was initialized |
| 3 | Unauthorized |
Caller is not the admin |
| 4 | InvalidAmount |
The vesting amount is zero or negative |
| 5 | InvalidSchedule |
cliff_ledger >= end_ledger, or end_ledger is in the past |
| 6 | NothingToClaim |
No tokens have vested since the last claim (or vested amount is zero) |
| 7 | AlreadyRevoked |
revoke was called on a schedule that has already been revoked |
| Code | Name | Description |
|---|---|---|
| 1 | AlreadyInitialized |
initialize was called on a contract that is already set up |
| 2 | NotInitialized |
An operation was attempted before the contract was initialized |
| 3 | Unauthorized |
Caller is not the admin |
| 4 | InvalidAmount |
Amount is zero or negative |
| 5 | NoStake |
Staker has no stake to unstake or claim from |
| 6 | InsufficientStake |
Requested unstake amount exceeds the staker's current stake |
| 7 | NoRewards |
No rewards are available to claim |
| Code | Name | Description |
|---|---|---|
| 1 | AlreadyInitialized |
initialize was called after the signer set was already configured |
| 2 | NotInitialized |
An operation was attempted before the multisig was initialized |
| 3 | InvalidThreshold |
Threshold is zero or greater than the number of signers |
| 4 | InvalidSigners |
Signer or approval lists are empty or contain duplicates |
| 5 | NotSigner |
Caller, approver, or signer is not part of the wallet signer set |
| 6 | TransactionNotFound |
Requested transaction ID does not exist |
| 7 | AlreadyExecuted |
Transaction has already been executed |
| 8 | AlreadySigned |
Signer already approved the transaction |
| 9 | ThresholdNotMet |
Transaction does not have enough signatures to execute |
| 10 | InsufficientApprovals |
Signer-management change lacks enough threshold approvals |
End-to-end working examples are provided in the examples/ directory:
| Example | Description |
|---|---|
examples/typescript/index.js |
Node.js script β deploys token, mints to buyer, runs full escrow lifecycle |
examples/shell/run.sh |
Equivalent shell script using the Stellar CLI |
Both examples target a local Stellar node. Start one with ./scripts/local-net.sh start before running.
npm install @stellar/stellar-sdk
TOKEN_CONTRACT_ID=<id> ESCROW_CONTRACT_ID=<id> node examples/typescript/index.js./examples/shell/run.shWe welcome contributions! See CONTRIBUTING.md for dev setup, test commands, code style, and the PR process.
- Directory Tree β Purpose of every directory in the repository
- FAQ β Common developer questions: setup, testing, deployment, feature flags, token customization
- System Architecture β High-level design, contract relationships, storage tiers, event model, and admin framework
- Contract API Reference β Full public API for all contracts (parameters, return types, errors)
- Upgrade Guide β Step-by-step on-chain WASM upgrade with timelock and key rotation
- Security Best Practices
- Integration Guide
- Deployment Guide
- Soroban Documentation
- Stellar Developer Discord
- Soroban Examples
- Freighter Wallet
- Stellar Laboratory
- Security Best Practices
- Token Interface Compliance ADR
- Batch Mint Design ADR
- Architecture Decision Records
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Ready to build on Soroban? Start with any template and customize it for your use case! π