Repository navigation
[Smart Contracts] Implement Permissionless Third-Party Top-Up & Automated Balance Refuel #1463
Description
Overview & Background
In payroll, SaaS subscriptions, and continuous grant disbursement models, payment streams often risk premature exhaustion if the original stream creator runs low on capital, forgets to deposit additional collateral, or is temporarily unavailable. Currently, FlowFi's top_up entrypoint strictly requires the stream creator's authorization:
sender.require_auth();This prevents external sponsors, automated treasury refuel bots (e.g., Gelato/Keepers), DAO multisigs, or affiliated parent entities from contributing funds to extend a vital stream's runway without transferring administrative ownership.
Detailed Problem Statement
- Unintended Stream Halts in Payroll:
- If a company's payroll wallet runs dry, team members or department leads cannot top up active employee streams from an emergency pool or subsidiary wallet.
- Keeper / Bot Automation Incompatibility:
- Automated keeper bots that monitor runway (e.g. "top up stream when remaining runway < 48 hours") cannot execute refuel transactions because they cannot sign on behalf of the stream's original sender.
- Sponsorship & Grant Matching Blockers:
- Web3 grant programs where community donors contribute matching funds directly into an active grantee stream cannot function under creator-only top-up constraints.
Technical Specification & Architecture
1. Permissionless Top-Up Entrypoint
Implement top_up_stream_from (or adjust top_up_stream) in contracts/stream_contract/src/lib.rs:
pub fn top_up_from(
env: Env,
funder: Address,
stream_id: u64,
amount: i128,
) -> Result<i128, StreamError>2. Authorization & Accounting Invariants
- Enforce
funder.require_auth(). - Validate that
amount > 0. - Load the stream via
storage::load_stream(&env, stream_id). - Enforce that the stream is active (
stream.is_active == true) and not cancelled or completed. - Transfer
amountofstream.token_addressfromfunderto the contract address via Soroban Token client. - Update
stream.deposited_amount += amount. - Recalculate remaining runway:
remaining_runway_seconds = (stream.deposited_amount - stream.withdrawn_amount) / stream.rate_per_second. - Extend storage TTL for the stream entry.
- Save the updated stream back to persistent storage.
3. Event Emission
Emit an extended event or a dedicated StreamRefueled event in contracts/stream_contract/src/events.rs:
pub fn emit_stream_refueled(
env: &Env,
stream_id: u64,
funder: &Address,
amount: i128,
new_total_deposited: i128,
)4. Cancellation Refund Equity
- Ensure
cancel_streamsemantics maintain solvency: unvested balance refunds to the originalsender(or document explicitly whether third-party funders waive claim to unvested amounts, treating top-ups as irrevocable donations to the stream principal).
Target Files
contracts/stream_contract/src/lib.rscontracts/stream_contract/src/events.rscontracts/stream_contract/src/storage.rscontracts/stream_contract/src/test.rs
Acceptance Criteria
- Third-party
fundercan successfully top up an existing active stream usingtop_up_from. - Unauthorized caller cannot spend
fundertokens (enforcesfunder.require_auth()). - Zero or negative amounts revert with
StreamError::InvalidAmount. - Cannot top up cancelled or completed streams (
StreamError::StreamNotActive). - Emits
StreamRefueledwith funder address, amount, and new total deposited balance. - Comprehensive tests in
test.rsverify multi-funder runway extension and post-refuel withdrawal consistency.
Activity
emarkees commentedon Sep 27, 2026
@emarkees has applied to work on this issue as part of the Stellar Wave Program's 9th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @emarkees to this issue.
drips-wave commentedon Sep 29, 2026
Congratulations, @emarkees! 🎉 Your application was accepted by the repo's maintainers, and the issue is due on September 30, 2026.
🧑💻 @emarkees: Please resolve the issue such that the repo's maintainers have enough time to review your contribution before the due date. You'll earn Points for completing the issue on-time, which will make you eligible for a share of the Stellar Wave Program's reward pool.
Warning
When opening a PR, please link it to this issue to ensure it gets tracked accurately. Points are awarded when this issue is marked as completed by the maintainer.
🤠 Repo maintainers: Please keep an eye on the contributor's progress and review their work before the due date. You can manage this issue, including adjusting its complexity and points, here.
🌊 Happy Wave 🌊
feat(stream_contract): implement permissionless third-party top-up (#…
grantfox-oss commentedon Oct 21, 2026
🎉 This issue has been marked as completed on GrantFox!
@emarkees's PR #1602 was approved and merged by @K1NGD4VID.
🏆 @emarkees: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (812 total points). Track your full progress on GrantFox.
👏 Great work, @emarkees! Keep contributing to LabsCrypt.
drips-wave commentedon Oct 21, 2026
This issue has been completed by @emarkees as part of the Stellar Wave Program's 10th Wave 🥳
😎 @emarkees: You earned 150 Points for completing this issue! Once the Wave's rewards are finalized, you'll be eligible for a percentage of the Wave's reward pool based on the percentage of total points you've earned. Learn more here. You can also Leave a review to share your experience working on this issue.
🧑💻 Repo maintainers: How'd the contributor do? Leave a review to share your experience working with them.