FluxoraSoroban streaming primitive

Lock tokens once. They accrue to the recipient every second until they are gone.

IllustrationClient-side arithmetic over fixed numbers. Not live chain state.
USDC vested
vested
0.0000000
refundable
1,000.0000000
deposited
1,000.0000000

The two terms change every frame. Their sum does not move by one stroop.

Testnet contract
CBCGTSCJ…EYGUTHXW
Protocol
27
Contract size
29,100 B
Audit
None yet

Fluxora is a payment streaming primitive for Soroban. A sender funds a stream with a start, an end, and optionally a cliff; value accrues against ledger time; the recipient withdraws whatever has accrued, whenever they want. Streams can be paused, topped up, transferred, and cancelled with exact settlement.

It is infrastructure, not an application. Payroll, vesting, grant disbursement and subscription billing are thin layers over the same contract.

How a stream works

Ordered — each state follows the last

  1. created

    The sender locks the full deposit. Start, end, and cliff are fixed. So are three capability flags — cancellable, pausable, transferable — which can never change afterwards, so a recipient can verify what the sender is able to do before accepting.

  2. cliff

    The cliff gates the payout; it does not delay accrual. At cliff_time the recipient becomes entitled to everything accrued since start_time, not merely what accrues after. Pass cliff_time == start_time for no cliff.

  3. accruing

    Value accrues against ledger time and is computed on read. Nothing runs in the background — Stellar has no scheduler. The recipient calls withdraw and the contract works out what they have earned at that instant.

  4. matured

    At end_time the whole deposit is vested. Accrual stops there and is clamped; no amount of elapsed time produces one stroop more than was deposited.

  5. settled

    Either the recipient draws the balance to zero and the stream is depleted, or the sender cancels and the unvested remainder is refunded exactly. A cancelled stream stays cancelled even once drained, so the two endings stay distinguishable.

The settlement guarantee

vested(t) + refundable(t) = deposited

Exactly, at every instant — no dust term. Vesting is recomputed from the cumulative schedule on every call rather than accumulated from per-interval deltas, so truncation error is re-derived from scratch each time instead of building up. Rounding is always down, in the recipient's disfavour, so the pool can never owe more than it holds. When a stream settles the residue is zero rather than small.

What you build on it

Contributor payroll
Salary that accrues per second instead of arriving monthly. A contributor draws whenever they like; a treasury commits once and stops running a payment schedule.
Token vesting with a cliff
A one-year cliff followed by linear vesting is the default grant shape. Set cliff_time and the contract enforces it; nothing releases before the date.
Milestone and grant disbursement
Fund a grant up front and let it stream. Pause when a milestone slips and the schedule stretches by exactly the paused duration rather than shortchanging anyone.
Subscription billing
A payer streams to a service continuously and stops by cancelling. The provider is paid for exactly the time consumed, to the stroop.
DAO compensation
Wrap create_stream in a policy contract so a smart account caps what can be committed per period. The core contract has no admin key to negotiate with.

Try it against the deployed contract

Live on testnet

The contract is deployed and callable now. There is no SDK yet, so this uses the Stellar CLI directly.

shell
# Read a live stream from the deployed testnet contract.
# Requires stellar-cli 27.x — the CLI major must match the network protocol.

stellar contract invoke \
  --id CBCGTSCJXBMPPPE4BPDIPYZXPE2J5TQEKD2KCS7VQF533NKKEYGUTHXW \
  --source-account <your-key> \
  --network testnet \
  --send=no \
  -- get_stream --stream_id 0

# Returns the full Stream struct: deposited, withdrawn, start_time, end_time,
# cliff_time, the three capability flags, paused_at, paused_total, status.
#
# Derive vested, withdrawable and refundable from that single response rather
# than making three calls — a public RPC URL is an endpoint, not a node, and
# separate calls can land on different ledgers.

What has been verified, and how

159 tests · 20,000 property cases nightly

ClaimHow it is verifiedFigure
vested(t) + refundable(t) = deposited, exactlyProperty test over random schedules, plus asserted after every operation in the suite20,000 cases
No operation reduces vested(t) for a fixed tEvery entry point measured with the clock frozen, in five stream states, across all 720 orderings of the six mutating operations4,320 measurements
Pooled balance always covers every stream's liabilityRe-checked after every single operation in randomized sequences, seeded for replay400 seeds nightly
The deployed contract matches the audited sourceInterface spec of the deployed contract compared byte-for-byte with the local buildsha256 match
Behaviour on a real network matches the test suiteEvery entry point called against live testnet, with assertions on on-chain state35 / 35 passing
A full batch stays inside protocol limitsMeasured against protocol 27 mainnet limits; the binding constraint is the event budget, not entry reads8,192 / 16,384 bytes

Deployment provenance

wasm hash
d47c96a344a79c614ab0dcf0eac62cc9384f6dc7f1d45c3f5109fb09658b035e
interface spec sha256
acdfd259c7f9a854d42c5da4cda43138fb71b757b604a21c6dac8a8a5a3a86d1

The interface of the deployed contract was compared byte-for-byte with the local build. Pin the wasm hash and treat a change in it as requiring a fresh read of the ABI.

Known limitations

What a green test suite does not prove

No audit

No third-party security audit has been performed. The property tests, the pool invariant and the randomized sequence suite are evidence of care, not a substitute for review.

Archival recovery is not yet proven on a live network

The SDK's test host silently auto-restores expired persistent entries instead of failing, so the suite proves that crossing the archive and restore boundary preserves accounting — but not the real sequence, where the read fails and the caller must resubmit with aRestoreFootprint operation. A canary entry was planted on testnet and archives around 19 August 2026. Until that round trip runs, treat TTL as half-proven.

Batch size is calibrated against one token

The cap of 16 is bounded by the contract event budget, and roughly half of the per-stream cost is the token's own transfer event rather than Fluxora's. It was measured against the Stellar Asset Contract; a token with a heavier event payload shifts the ceiling down.

Resource figures understate a real deployment

Measurements register contracts natively, so Wasm instantiation and execution costs are skipped and reported instruction counts are lower than production. Entry counts and event bytes — what the batch cap actually derives from — are accurate.

Status

Plainly

Built

  • Core contract — create, withdraw, cancel, pause, resume, top up, transfer recipient
  • Bounded batch withdrawal and permissionless TTL extension
  • Deployed to testnet and exercised end to end against the live network
  • Frozen ABI, verified byte-identical to the deployment

In progress

  • Verifying archival recovery against live testnet — a canary entry archives around 19 August 2026
  • Indexer and keeper for TTL sweeps

Planned

  • TypeScript SDK — does not exist yet
  • Third-party security audit — has not been performed
  • Mainnet deployment, after the audit
  • Delegated withdrawal, as a v1.1 addition with its own threat model