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 (
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). - Status — Active, Paused, Completed, Cancelled.
- Methods (stubs) —
init,create_stream,pause_stream,resume_stream,cancel_stream,withdraw,calculate_accrued,get_stream_state.
Implementation is scaffolded; storage, token transfers, and events are left for you to complete.
- Rust (edition 2021)
- soroban-sdk (Stellar Soroban)
- Build target:
wasm32-unknown-unknownfor deployment
fluxora-contracts/
Cargo.toml # workspace
.env.example # env var template (copy → .env, never commit)
scripts/
deploy-testnet.sh # ← build + deploy + init script (see below)
contracts/
stream/
Cargo.toml
src/
lib.rs # contract types and impl
test.rs # unit tests
tests/
integration_suite.rs # integration tests (Soroban testutils)
- Rust 1.70+
- Stellar CLI — install guide
rustup target add wasm32-unknown-unknownFrom the repo root:
cargo build --release -p fluxora_streamWASM output is under target/wasm32-unknown-unknown/release/fluxora_stream.wasm.
cargo test -p fluxora_streamThis runs both:
- Unit tests in
contracts/stream/src/test.rs - Integration tests in
contracts/stream/tests/integration_suite.rs
The integration suite invokes the contract with Soroban testutils and covers:
initcreate_streamwithdrawget_stream_state- A full stream lifecycle from create to completed withdrawal
- Key edge cases (
inittwice, pre-cliff withdrawal, unknown stream id, underfunded deposit)
Security note: Never commit secret keys. Use
.envlocally or CI secrets in production pipelines.
cp .env.example .env
# Open .env and fill in the three required values| Variable | Required | Description |
|---|---|---|
STELLAR_SECRET_KEY |
✅ | Stellar account secret key (S...). Fund via testnet faucet. |
STELLAR_TOKEN_ADDRESS |
✅ | Contract address of the token (USDC-SAC or test token) on testnet. |
STELLAR_ADMIN_ADDRESS |
✅ | Public key (G...) of the admin/treasury wallet. |
STELLAR_NETWORK |
optional | Network alias (default: testnet). |
STELLAR_RPC_URL |
optional | Custom RPC endpoint (default: https://soroban-testnet.stellar.org). |
SKIP_INIT |
optional | Set to 1 to skip the automatic init invocation after deploy. |
WASM_ID_FILE |
optional | File to persist the uploaded WASM ID (default: .wasm_id). |
CONTRACT_ID_FILE |
optional | File to persist the deployed contract ID (default: .contract_id). |
source .env
bash scripts/deploy-testnet.shThe script will:
- Validate all required env vars and CLI prerequisites.
- Ensure the
wasm32-unknown-unknowntarget is installed. - Build the contract in release mode.
- Upload the WASM binary to testnet (idempotent — skips re-upload if the binary hash is unchanged).
- Deploy the contract (idempotent — skips re-deploy if
.contract_idalready exists). - Invoke
initwith your token and admin address.
The script stores the deployed WASM ID in .wasm_id and the contract ID in .contract_id (both git-ignored). Re-running the script:
- Will skip the WASM upload if the binary has not changed (SHA-256 match).
- Will skip the contract deploy if
.contract_idalready exists. - To force a full re-deploy, delete
.wasm_id,.wasm_id.sha256, and.contract_id.
SKIP_INIT=1 bash scripts/deploy-testnet.sh# Read the saved contract ID
CONTRACT_ID=$(cat .contract_id)
# Create a stream
stellar contract invoke --id "$CONTRACT_ID" --network testnet --source "$STELLAR_SECRET_KEY" \
-- create_stream \
--sender <G_SENDER_ADDRESS> \
--recipient <G_RECIPIENT_ADDRESS> \
--deposit_amount 1000000 \
--rate_per_second 100 \
--cliff_time 1700000000 \
--end_time 1700086400
# Get stream state
stellar contract invoke --id "$CONTRACT_ID" --network testnet --source "$STELLAR_SECRET_KEY" \
-- get_stream_state --stream_id 0
# Withdraw accrued amount
stellar contract invoke --id "$CONTRACT_ID" --network testnet --source "$STELLAR_SECRET_KEY" \
-- withdraw --stream_id 0Accrued = min((current_time - start_time) × rate_per_second, deposit_amount)
Withdrawable = Accrued - withdrawn_amount
→ 0 before cliff_time
- fluxora-backend — API and Horizon sync
- fluxora-frontend — Dashboard and recipient UI
Each is a separate Git repository.