Soroban smart contracts for the Fluxora treasury streaming protocol on Stellar. Stream USDC from a treasury to recipients over time with configurable rate, duration, and cliff.
- Stream contract — Lifecycle, accrual formula, cliff/end_time, access control, events, and error codes.
- Security — CEI ordering, token trust model, authorization paths, overflow protection.
- Upgrade strategy — CONTRACT_VERSION policy, breaking-change classification, migration runbook.
- Deployment — Step-by-step testnet deployment checklist.
- Storage layout — Contract storage architecture, key design, and TTL policies.
- Audit preparation — Entry-points and invariants for auditors.
- Error codes — Full ContractError reference.
- Events — Emitted event shapes and topics.
- Stream contract (
contracts/stream) — Lock USDC, accrue per second, withdraw on demand. - Data model —
Stream(sender, recipient, deposit_amount, rate_per_second, start/cliff/end time, withdrawn_amount, status, cancelled_at). - Status —
Active,Paused,Completed,Cancelled.
| Entry-point | Caller | Description |
|---|---|---|
init |
Bootstrap admin | One-shot initialisation: set token and admin |
create_stream |
Sender | Create a single stream and pull deposit |
create_streams |
Sender | Batch-create streams in one atomic transaction |
pause_stream |
Sender | Halt withdrawals (accrual continues) |
resume_stream |
Sender | Re-enable withdrawals |
cancel_stream |
Sender | Terminate stream; refund unstreamed tokens to sender |
withdraw |
Recipient | Pull accrued tokens to recipient address |
withdraw_to |
Recipient | Pull accrued tokens to a specified destination |
batch_withdraw |
Recipient | Withdraw from multiple streams in one call |
top_up_stream |
Any funder | Add tokens to an existing stream's deposit |
update_rate_per_second |
Sender | Change the streaming rate |
shorten_stream_end_time |
Sender | Move end_time earlier; refunds excess deposit |
extend_stream_end_time |
Sender | Move end_time later |
close_completed_stream |
Anyone | Remove a completed stream from storage (cleanup) |
pause_stream_as_admin |
Admin | Administrative pause override |
resume_stream_as_admin |
Admin | Administrative resume override |
cancel_stream_as_admin |
Admin | Administrative cancel override |
set_admin |
Admin | Rotate the admin key |
set_contract_paused |
Admin | Global emergency pause (blocks new stream creation) |
calculate_accrued |
Anyone | View: accrued amount at current ledger time |
get_withdrawable |
Anyone | View: withdrawable amount at current ledger time |
get_claimable_at |
Anyone | View: simulated claimable amount at an arbitrary timestamp |
get_stream_state |
Anyone | View: full stream struct |
get_stream_count |
Anyone | View: total number of streams created |
get_recipient_streams |
Anyone | View: all stream IDs for a recipient (sorted) |
get_recipient_stream_count |
Anyone | View: number of streams for a recipient |
get_config |
Anyone | View: token address and admin address |
version |
Anyone | View: CONTRACT_VERSION constant (pre-flight check) |
cancel_stream and cancel_stream_as_admin are valid only when status is Active or Paused. Streams in Completed or Cancelled state return ContractError::InvalidState. After cancellation, accrual is frozen at cancelled_at; the recipient may still withdraw the frozen accrued amount.
- Rust (edition 2021)
- soroban-sdk 21.7.7 (Stellar Soroban)
- Build target:
wasm32-unknown-unknownfor deployment
This project pins dependencies for reproducible builds and auditor compatibility:
| Component | Version | Location | Purpose |
|---|---|---|---|
| Rust | 1.75 | rust-toolchain.toml |
Ensures consistent WASM compilation |
| soroban-sdk | 21.7.7 | contracts/stream/Cargo.toml |
Locked to tested Stellar Soroban network version |
When upgrading versions:
- Update
rust-toolchain.toml→ runrustup update→ rebuild and test - Update
soroban-sdkversion inCargo.toml→ update lock file → run full test suite - Verify compatibility with the target Stellar network (testnet, mainnet)
- Document the change in the PR or release notes
git clone https://github.com/Fluxora-Org/Fluxora-Contracts.git
cd Fluxora-Contracts- Rust 1.75+ — Pinned in
rust-toolchain.toml(auto-enforced viarustup) - Soroban SDK 21.7.7 — Pinned in
contracts/stream/Cargo.tomlfor reproducible builds - Stellar CLI (optional, for deploy/test on network)
Install dependencies:
rustup update stable
rustup target add wasm32-unknown-unknownThen verify:
rustc --version # Should show 1.75 or newer
cargo --version
stellar --version # Only if installing Stellar CLIFrom the repo root:
# Development build (faster compile, for local testing)
cargo build -p fluxora_stream
# Release build (optimized WASM for deployment)
cargo build --release -p fluxora_stream --target wasm32-unknown-unknownRelease WASM output: target/wasm32-unknown-unknown/release/fluxora_stream.wasm.
cargo test -p fluxora_streamRuns all unit and integration tests. No environment variables or external services required — Soroban's in-process test environment (soroban_sdk::testutils) simulates the ledger and a mock Stellar asset in memory.
Test files:
- Unit tests:
contracts/stream/src/test.rs— contract logic, accrual math, auth, edge cases, i128 boundary scenarios, version policy. - Integration tests:
contracts/stream/tests/integration_suite.rs— full flows withinit,create_stream,withdraw,get_stream_state, lifecycle transitions, and edge cases.
See docs/DEPLOYMENT.md for the complete step-by-step deployment checklist.
Quick start:
cp .env.example .env
# Edit .env with your STELLAR_SECRET_KEY, STELLAR_TOKEN_ADDRESS, STELLAR_ADMIN_ADDRESS
source .env
bash script/deploy-testnet.shContract ID is saved to .contract_id. Verify the deployment with:
stellar contract invoke --id $(cat .contract_id) -- version
stellar contract invoke --id $(cat .contract_id) -- get_configfluxora-contracts/
Cargo.toml # workspace
rust-toolchain.toml # pinned Rust version
contracts/
stream/
Cargo.toml
src/
lib.rs # contract types, storage, and all entry-points
accrual.rs # pure accrual math (calculate_accrued_amount)
test.rs # unit tests
tests/
integration_suite.rs # integration tests (Soroban testutils)
docs/
streaming.md # lifecycle, accrual, access control, events
security.md # CEI ordering, token trust model, auth paths
upgrade.md # CONTRACT_VERSION policy and migration runbook
storage.md # storage layout and TTL policies
audit.md # entry-points and invariants for auditors
error.md # ContractError reference
events.md # emitted event shapes
DEPLOYMENT.md # testnet deployment checklist
gas.md # gas and budget notes
script/
deploy-testnet.sh # automated testnet deployment script
if current_time < cliff_time → 0
else → min((min(current_time, end_time) − start_time) × rate_per_second, deposit_amount)
- Withdrawable =
accrued − withdrawn_amount - Accrual is capped at
end_time— no extra accrual after the stream ends. - Multiplication overflow in accrual falls back to
deposit_amount(safe upper bound). - Cancelled streams: accrual is frozen at
cancelled_at. - Completed streams:
calculate_accruedreturnsdeposit_amountdeterministically.
After each CI build, the pipeline computes a SHA256 hash of the contract WASM artifact and uploads it as a CI artifact. This allows deployers and auditors to verify that the deployed contract matches the tested build.
To verify a deployment:
- Download the hash artifact from the CI run (GitHub Actions → Artifacts →
fluxora_stream-wasm-hash). - Compute the SHA256 hash of your local WASM file:
sha256sum target/wasm32-unknown-unknown/release/fluxora_stream.wasm
- Compare the output to the CI hash file. A match confirms your binary is identical to the tested build.
- fluxora-backend — API and Horizon sync
- fluxora-frontend — Dashboard and recipient UI
Each is a separate Git repository.
Please read CONTRIBUTING.md for details on the development workflow, branch naming, and testing requirements (including the 95% test coverage standard).
See CHANGELOG.md for a full history of changes between contract versions.