Soroban smart contracts for Stellabill — prepaid USDC subscription billing on the Stellar network. This repository contains the on-chain logic for recurring payments, subscriber vaults, and merchant payouts.
- What’s in this repo
- Prerequisites
- Local setup
- Build, test, and deploy
- Contributing (open source)
- Project layout
- License
A single Soroban contract that implements a prepaid subscription vault for recurring USDC billing:
| Concept | Description |
|---|---|
| Subscriber | User who holds a subscription; funds are held in the contract (vault) for that subscription. |
| Merchant | Recipient of recurring payments; can withdraw accumulated USDC. |
| Subscription | Agreement between subscriber and merchant: amount, billing interval, status (active/paused/cancelled), and prepaid balance. |
Main capabilities (current / planned):
init— Set the USDC token address and admin (e.g. billing backend).create_subscription— Subscriber creates a subscription (subscriber, merchant, amount, interval, usage flag). Auth: subscriber.deposit_funds— Subscriber tops up prepaid balance for a subscription. Auth: subscriber.charge_subscription— Billing engine charges one interval: deduct from vault, pay merchant, update last payment time. (Intended to be restricted to admin/authorized caller.)cancel_subscription— Subscriber or merchant cancels; remaining balance can be withdrawn by subscriber. Auth: subscriber or merchant.pause_subscription— Pause so no charges occur until resumed. Auth: subscriber or merchant.withdraw_merchant_funds— Merchant withdraws accumulated USDC. Auth: merchant.get_subscription— Read subscription by id (for indexers and UIs).
Types:
Subscription—subscriber,merchant,amount,interval_seconds,last_payment_timestamp,status,prepaid_balance,usage_enabled.SubscriptionStatus—Active,Paused,Cancelled,InsufficientBalance.Error—NotFound,Unauthorized.
Documentation: Subscription lifecycle and state machine — states, transitions, on-chain representation, and invariants.
The contract is in early development; several functions still have TODO placeholders (e.g. token transfers, admin checks, full charge/withdraw logic). See the source in contracts/subscription_vault/src/lib.rs for details.
- Rust (latest stable, e.g. 1.75+):
https://rustup.rs
rustup default stable - Soroban CLI:
https://developers.stellar.org/docs/tools/soroban-cli/install
Used to build WASM and run tests/deploy. - Stellar / Soroban basics:
https://developers.stellar.org/docs
Optional but helpful for contributing.
git clone https://github.com/YOUR_ORG/stellabill-contracts.git
cd stellabill-contracts(Replace YOUR_ORG with the actual org or user.)
- Install Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shthenrustup default stable. - Install Soroban CLI per the official install guide.
rustc --version
cargo --version
soroban --versioncargo build
cargo testFrom the repo root, this builds the workspace and runs the contract unit tests (including subscription_vault tests in contracts/subscription_vault/src/test.rs).
soroban contract buildThis produces the WASM under target/ for deployment to Stellar (e.g. testnet/mainnet via Soroban CLI or your CI/CD).
| Task | Command |
|---|---|
| Build workspace | cargo build |
| Run tests | cargo test |
| Build contract WASM | soroban contract build |
| Run with Soroban CLI (e.g. testnet) | See Stellar docs for soroban contract deploy and invoke. |
We welcome contributions from the community. Here’s how to get started and how we work.
- Read this README and the Stellar / Soroban docs.
- Check GitHub Issues for “good first issue” or “help wanted” labels.
- If you want to change behavior or add a feature, open an issue first so we can align on design.
- Fork the repo on GitHub and clone your fork.
- Create a branch from
main(or default branch):
git checkout -b feature/your-featureorfix/your-fix. - Set up locally as in Local setup. Run
cargo testandcargo buildto ensure everything passes. - Make changes in small, logical commits. Keep messages clear (e.g. “Add admin check to charge_subscription”, “Fix subscription id overflow”).
- Run tests and build before pushing:
cargo test && cargo buildand, if you touch contract interface,soroban contract build. - Push to your fork and open a Pull Request against the upstream
main(or default branch).
- Scope: One logical change per PR when possible (easier review and atomic history).
- Tests: New behavior should be covered by unit tests in the contract crate; existing tests must stay green.
- Docs: If you add or change a public function or type, update the README or inline docs as needed.
- Description: Use the PR description to explain the “why” and how to verify (e.g. steps or test commands).
- Rust: Follow common Rust style (
cargo fmt,cargo clippy). Nounwrap()in contract logic without a clear justification; preferResultand explicit errors. - Soroban: Use
Envfor storage and auth; keep contract functions narrow and well-documented. - Security: Any change that touches auth, token transfers, or admin rights will get extra review. When in doubt, open an issue first.
- Questions: Open a GitHub Discussion or an issue with the “question” label.
- Bugs: Open an issue with steps to reproduce, environment (Rust/Soroban versions), and logs if relevant.
- Ideas: Use Discussions or an issue with “enhancement” so we can track and discuss.
We expect all contributors and maintainers to be respectful and inclusive. By participating, you agree to uphold a constructive and professional environment. Specific CoC details (if any) will be linked in the repo (e.g. CODE_OF_CONDUCT.md or in the GitHub community guidelines).
stellabill-contracts/
├── Cargo.toml # Workspace root; lists contract crates
├── Cargo.lock # Locked dependencies (reproducible builds)
├── README.md # This file
├── .gitignore
├── docs/ # Contract documentation
│ ├── subscription_lifecycle.md # Subscription lifecycle, state machine, on-chain representation
│ ├── subscription_state_machine.md
│ ├── batch_charge.md
│ ├── billing_intervals.md
│ ├── topup_estimation.md
│ └── safe_math.md
└── contracts/
└── subscription_vault/ # Prepaid subscription vault contract
├── Cargo.toml
└── src/
├── lib.rs # Contract logic and types
└── test.rs # Unit tests
See the LICENSE file in this repository (add one if not present). Contributions are accepted under the same license.